Show dialog when user chnages the region

1. show dialog
2. change the region of the top locale

Bug: 385047778
Flag: com.android.settings.flags.regional_preferences_api_enabled
Test: check hsv, atest
Change-Id: I9746cdec670899b3768dcd1e0aa59e1959dd7e06
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7386eab..c4c7fec 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -479,6 +479,12 @@
     <!-- Link for Locale helper page. [CHAR LIMIT=NONE]-->
     <string name="link_locale_picker_footer_learn_more" translatable="false">https://support.google.com/android?p=per_language_app_settings</string>
 
+    <!-- Title for asking to change system region or not. [CHAR LIMIT=50]-->
+    <string name="title_change_system_region">Change region to %s ?</string>
+
+    <!-- The content of a confirmation dialog indicating the impact when the user change the system region. [CHAR LIMIT=NONE]-->
+    <string name="desc_notice_device_region_change">Your device will keep %s as a system language</string>
+
     <!-- Title for asking to change system locale or not. [CHAR LIMIT=50]-->
     <string name="title_change_system_locale">Change system language to %s ?</string>
 
diff --git a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
index 3cf7683..ebd3f88 100644
--- a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
+++ b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java
@@ -33,6 +33,10 @@
 import com.android.internal.app.LocaleStore;
 import com.android.settings.R;
 import com.android.settings.core.SettingsBaseActivity;
+import com.android.settings.flags.Flags;
+import com.android.settings.regionalpreferences.RegionDialogFragment;
+
+import java.util.Locale;
 
 /**
  * An activity to show the locale picker page.
@@ -45,6 +49,10 @@
     private static final String TAG = LocalePickerWithRegionActivity.class.getSimpleName();
     private static final String PARENT_FRAGMENT_NAME = "localeListEditor";
     private static final String CHILD_FRAGMENT_NAME = "LocalePickerWithRegion";
+    private static final int DIALOG_CHANGE_LOCALE_REGION = 1;
+    private static final String ARG_DIALOG_TYPE = "arg_dialog_type";
+    private static final String ARG_TARGET_LOCALE = "arg_target_locale";
+    private static final String TAG_DIALOG_CHANGE_REGION = "dialog_change_region";
 
     private LocalePickerWithRegion mSelector;
 
@@ -102,6 +110,37 @@
 
     @Override
     public void onLocaleSelected(LocaleStore.LocaleInfo locale) {
+        if (Flags.regionalPreferencesApiEnabled()) {
+            if (sameLanguageAndScript(locale.getLocale(), Locale.getDefault())) {
+                Bundle args = new Bundle();
+                args.putInt(ARG_DIALOG_TYPE, DIALOG_CHANGE_LOCALE_REGION);
+                args.putSerializable(ARG_TARGET_LOCALE, locale);
+                RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance();
+                regionDialogFragment.setArguments(args);
+                regionDialogFragment.show(getSupportFragmentManager(), TAG_DIALOG_CHANGE_REGION);
+            } else {
+                dispose(locale);
+            }
+        } else {
+            dispose(locale);
+        }
+    }
+
+    private static boolean sameLanguageAndScript(Locale source, Locale target) {
+        String sourceLanguage = source.getLanguage();
+        String targetLanguage = target.getLanguage();
+        String sourceLocaleScript = source.getScript();
+        String targetLocaleScript = target.getScript();
+        if (sourceLanguage.equals(targetLanguage)) {
+            if (!sourceLocaleScript.isEmpty() && !targetLocaleScript.isEmpty()) {
+                return sourceLocaleScript.equals(targetLocaleScript);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private void dispose(LocaleStore.LocaleInfo locale) {
         final Intent intent = new Intent();
         intent.putExtra(LocaleListEditor.INTENT_LOCALE_KEY, locale);
         setResult(RESULT_OK, intent);
diff --git a/src/com/android/settings/regionalpreferences/RegionDialogFragment.java b/src/com/android/settings/regionalpreferences/RegionDialogFragment.java
new file mode 100644
index 0000000..3f6aa54
--- /dev/null
+++ b/src/com/android/settings/regionalpreferences/RegionDialogFragment.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2024 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.regionalpreferences;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.LocaleList;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.internal.app.LocalePicker;
+import com.android.internal.app.LocaleStore;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * Create a dialog for system region events.
+ */
+public class RegionDialogFragment extends InstrumentedDialogFragment {
+    private static final String TAG = "RegionDialogFragment";
+    static final int DIALOG_CHANGE_LOCALE_REGION = 1;
+    static final String ARG_DIALOG_TYPE = "arg_dialog_type";
+    static final String ARG_TARGET_LOCALE = "arg_target_locale";
+
+    /**
+     * Use this factory method to create a new instance of
+     * this fragment using the provided parameters.
+     *
+     * @return A new instance of fragment RegionDialogFragment.
+     */
+    @NonNull
+    public static RegionDialogFragment newInstance() {
+        return new RegionDialogFragment();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return 0;
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        // TODO(385834414): Migrate to use MaterialAlertDialogBuilder
+        RegionDialogController controller = getRegionDialogController(getContext(), this);
+        RegionDialogController.DialogContent dialogContent = controller.getDialogContent();
+        ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(getContext()).inflate(
+                R.layout.locale_dialog, null);
+        setDialogTitle(viewGroup, dialogContent.mTitle);
+        setDialogMessage(viewGroup, dialogContent.mMessage);
+        AlertDialog.Builder builder = new AlertDialog.Builder(getContext()).setView(viewGroup);
+        if (!dialogContent.mPositiveButton.isEmpty()) {
+            builder.setPositiveButton(dialogContent.mPositiveButton, controller);
+        }
+        if (!dialogContent.mNegativeButton.isEmpty()) {
+            builder.setNegativeButton(dialogContent.mNegativeButton, controller);
+        }
+        return builder.create();
+    }
+
+    private static void setDialogTitle(View root, String content) {
+        TextView titleView = root.findViewById(R.id.dialog_title);
+        if (titleView == null) {
+            return;
+        }
+        titleView.setText(content);
+    }
+
+    private static void setDialogMessage(View root, String content) {
+        TextView textView = root.findViewById(R.id.dialog_msg);
+        if (textView == null) {
+            return;
+        }
+        textView.setText(content);
+    }
+
+    @VisibleForTesting
+    RegionDialogController getRegionDialogController(Context context,
+            RegionDialogFragment dialogFragment) {
+        return new RegionDialogController(context, dialogFragment);
+    }
+
+    class RegionDialogController implements DialogInterface.OnClickListener {
+        private final Context mContext;
+        private final int mDialogType;
+        private final LocaleStore.LocaleInfo mLocaleInfo;
+
+        RegionDialogController(
+                @NonNull Context context, @NonNull RegionDialogFragment dialogFragment) {
+            mContext = context;
+            Bundle arguments = dialogFragment.getArguments();
+            mDialogType = arguments.getInt(ARG_DIALOG_TYPE);
+            mLocaleInfo = (LocaleStore.LocaleInfo) arguments.getSerializable(ARG_TARGET_LOCALE);
+        }
+
+        @Override
+        public void onClick(@NonNull DialogInterface dialog, int which) {
+            if (mDialogType == DIALOG_CHANGE_LOCALE_REGION) {
+                if (which == DialogInterface.BUTTON_POSITIVE) {
+                    updateRegion(mLocaleInfo.getLocale().toLanguageTag());
+                }
+                dismiss();
+                if (getActivity() != null) {
+                    getActivity().finish();
+                }
+            }
+        }
+
+        @VisibleForTesting
+        DialogContent getDialogContent() {
+            DialogContent dialogContent = new DialogContent();
+            switch (mDialogType) {
+                case DIALOG_CHANGE_LOCALE_REGION:
+                    dialogContent.mTitle = String.format(mContext.getString(
+                        R.string.title_change_system_region),
+                        mLocaleInfo.getLocale().getDisplayCountry());
+                    dialogContent.mMessage = mContext.getString(
+                        R.string.desc_notice_device_region_change,
+                        Locale.getDefault().getDisplayLanguage());
+                    dialogContent.mPositiveButton = mContext.getString(
+                        R.string.button_label_confirmation_of_system_locale_change);
+                    dialogContent.mNegativeButton = mContext.getString(R.string.cancel);
+                    break;
+                default:
+                    break;
+            }
+            return dialogContent;
+        }
+
+        private void updateRegion(String selectedLanguageTag) {
+            LocaleList localeList = LocaleList.getDefault();
+            Locale systemLocale = Locale.getDefault();
+            Set<Character> extensionKeys = systemLocale.getExtensionKeys();
+            Locale selectedLocale = Locale.forLanguageTag(selectedLanguageTag);
+            Locale.Builder builder = new Locale.Builder();
+            builder.setLocale(selectedLocale);
+            if (!extensionKeys.isEmpty()) {
+                for (Character extKey : extensionKeys) {
+                    builder.setExtension(extKey, systemLocale.getExtension(extKey));
+                }
+            }
+            Locale newLocale = builder.build();
+            Locale[] resultLocales = new Locale[localeList.size()];
+            resultLocales[0] = newLocale;
+            for (int i = 1; i < localeList.size(); i++) {
+                resultLocales[i] = localeList.get(i);
+            }
+            LocalePicker.updateLocales(new LocaleList(resultLocales));
+        }
+
+        @VisibleForTesting
+        static class DialogContent {
+            String mTitle = "";
+            String mMessage = "";
+            String mPositiveButton = "";
+            String mNegativeButton = "";
+        }
+    }
+}
diff --git a/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java b/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java
index 6c2c8b6..cb3b82b 100644
--- a/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java
+++ b/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java
@@ -17,18 +17,19 @@
 package com.android.settings.regionalpreferences;
 
 import android.content.Context;
-import android.os.LocaleList;
+import android.os.Bundle;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
 
 import com.android.internal.annotations.Initializer;
 import com.android.internal.app.LocaleCollectorBase;
 import com.android.internal.app.LocaleHelper;
-import com.android.internal.app.LocalePicker;
 import com.android.internal.app.LocaleStore;
 import com.android.internal.app.LocaleStore.LocaleInfo;
 import com.android.settings.core.BasePreferenceController;
@@ -45,9 +46,12 @@
 
     private static final String TAG = "RegionPickerBaseListPreferenceController";
     private static final String KEY_SUGGESTED = "suggested";
+    private static final String TAG_DIALOG_CHANGE_REGION = "dialog_change_region";
     private PreferenceCategory mPreferenceCategory;
     private Set<LocaleInfo> mLocaleList;
     private ArrayList<LocaleInfo> mLocaleOptions;
+    private Fragment mParent;
+    private FragmentManager mFragmentManager;
 
     public RegionPickerBaseListPreferenceController(@NonNull Context context,
             @NonNull String preferenceKey) {
@@ -58,6 +62,10 @@
         mLocaleOptions.ensureCapacity(mLocaleList.size());
     }
 
+    public void setFragment(@NonNull Fragment parent) {
+        mParent = parent;
+    }
+
     @Override
     @Initializer
     public void displayPreference(@NonNull PreferenceScreen screen) {
@@ -156,28 +164,14 @@
         if (localeInfo.getLocale().equals(Locale.getDefault())) {
             return;
         }
-        updateRegion(localeInfo.getLocale().toLanguageTag());
-        updatePreferences();
-    }
 
-    private void updateRegion(String selectedLanguageTag) {
-        LocaleList localeList = LocaleList.getDefault();
-        Locale systemLocale = Locale.getDefault();
-        Set<Character> extensionKeys = systemLocale.getExtensionKeys();
-        Locale selectedLocale = Locale.forLanguageTag(selectedLanguageTag);
-        Locale.Builder builder = new Locale.Builder();
-        builder.setLocale(selectedLocale);
-        if (!extensionKeys.isEmpty()) {
-            for (Character extKey : extensionKeys) {
-                builder.setExtension(extKey, systemLocale.getExtension(extKey));
-            }
-        }
-        Locale newLocale = builder.build();
-        Locale[] resultLocales = new Locale[localeList.size()];
-        resultLocales[0] = newLocale;
-        for (int i = 1; i < localeList.size(); i++) {
-            resultLocales[i] = localeList.get(i);
-        }
-        LocalePicker.updateLocales(new LocaleList(resultLocales));
+        mFragmentManager = mParent.getChildFragmentManager();
+        Bundle args = new Bundle();
+        args.putInt(RegionDialogFragment.ARG_DIALOG_TYPE,
+                RegionDialogFragment.DIALOG_CHANGE_LOCALE_REGION);
+        args.putSerializable(RegionDialogFragment.ARG_TARGET_LOCALE, localeInfo);
+        RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance();
+        regionDialogFragment.setArguments(args);
+        regionDialogFragment.show(mFragmentManager, TAG_DIALOG_CHANGE_REGION);
     }
 }
diff --git a/src/com/android/settings/regionalpreferences/RegionPickerFragment.java b/src/com/android/settings/regionalpreferences/RegionPickerFragment.java
index b675d2a..b1759f1 100644
--- a/src/com/android/settings/regionalpreferences/RegionPickerFragment.java
+++ b/src/com/android/settings/regionalpreferences/RegionPickerFragment.java
@@ -75,6 +75,8 @@
                 new SystemRegionAllListPreferenceController(
                     context, KEY_PREFERENCE_SYSTEM_REGION_LIST, parentLocaleInfo);
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        mSuggestedListPreferenceController.setFragment(this);
+        mSystemRegionAllListPreferenceController.setFragment(this);
         controllers.add(mSuggestedListPreferenceController);
         controllers.add(mSystemRegionAllListPreferenceController);
         return controllers;
diff --git a/tests/robotests/src/com/android/settings/localepicker/LocalePickerWithRegionActivityTest.java b/tests/robotests/src/com/android/settings/localepicker/LocalePickerWithRegionActivityTest.java
index b254147..f6096d1 100644
--- a/tests/robotests/src/com/android/settings/localepicker/LocalePickerWithRegionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/localepicker/LocalePickerWithRegionActivityTest.java
@@ -6,10 +6,14 @@
 import static org.mockito.Mockito.spy;
 
 import android.app.Activity;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import com.android.internal.app.LocaleStore;
+import com.android.settings.flags.Flags;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
@@ -24,6 +28,8 @@
 
     private LocalePickerWithRegionActivity mActivity;
 
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -33,6 +39,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_REGIONAL_PREFERENCES_API_ENABLED)
     public void onLocaleSelected_resultShouldBeOK() {
         final ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
         mActivity.onLocaleSelected(mock(LocaleStore.LocaleInfo.class));
@@ -41,6 +48,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_REGIONAL_PREFERENCES_API_ENABLED)
     public void onLocaleSelected_localeInfoShouldBeSentBack() {
         final ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
         mActivity.onLocaleSelected(mock(LocaleStore.LocaleInfo.class));