From 3cbb6f86802ade7aac51234a070b6f623d829081 Mon Sep 17 00:00:00 2001 From: tom hsu Date: Thu, 11 Aug 2022 23:51:24 +0800 Subject: [PATCH 1/5] [Languages] Add new information to system language page. - Add top Intro preference - Add footer preference - Add sub string to language picker - Modify title of app locale pages Bug: 242182598 Add information to system language page. Bug: 241600418 [Panlingual] Change strings on App languages Test: Maunal test Change-Id: I9bca8911e8e70c97c273294b3c9d1d73d4ea0cb2 --- res/layout/locale_drag_cell.xml | 11 +++ res/values/strings.xml | 24 +++++- res/xml/languages.xml | 42 +++++++++++ .../LocaleDragAndDropAdapter.java | 3 +- .../settings/localepicker/LocaleDragCell.java | 10 +++ .../LocaleHelperPreferenceController.java | 74 +++++++++++++++++++ .../localepicker/LocaleListEditor.java | 27 +++++-- .../LocaleHelperPreferenceControllerTest.java | 59 +++++++++++++++ 8 files changed, 238 insertions(+), 12 deletions(-) create mode 100644 res/xml/languages.xml create mode 100644 src/com/android/settings/localepicker/LocaleHelperPreferenceController.java create mode 100644 tests/unit/src/com/android/settings/localepicker/LocaleHelperPreferenceControllerTest.java diff --git a/res/layout/locale_drag_cell.xml b/res/layout/locale_drag_cell.xml index 7b932f39a02..47bf70a473e 100644 --- a/res/layout/locale_drag_cell.xml +++ b/res/layout/locale_drag_cell.xml @@ -56,6 +56,17 @@ android:layout_toStartOf="@+id/dragHandle" android:layout_below="@id/label"/> + + Languages + + Preferred language order + + + System language + Remove @@ -497,13 +503,13 @@ Preferred Language - App Languages + App languages Set the language for each app - App Language + App language Suggested languages @@ -526,6 +532,18 @@ Only apps that support language selection are shown here. + + Your system, apps, and websites use the first supported language from your preferred languages. + + + To select a language for each app, go to app language settings. + + + Learn more about languages + + + https://support.google.com/android?p=per_language_app_settings + Remove selected language? @@ -541,7 +559,7 @@ Keep at least one preferred language - May not be available in some apps + Not available as system language Move up diff --git a/res/xml/languages.xml b/res/xml/languages.xml new file mode 100644 index 00000000000..0f455407645 --- /dev/null +++ b/res/xml/languages.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java index ab9110d01ab..b3c2e3071af 100644 --- a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java +++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java @@ -43,7 +43,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; - class LocaleDragAndDropAdapter extends RecyclerView.Adapter { @@ -154,8 +153,10 @@ class LocaleDragAndDropAdapter final LocaleDragCell dragCell = holder.getLocaleDragCell(); final String label = feedItem.getFullNameNative(); final String description = feedItem.getFullNameInUiLanguage(); + dragCell.setLabelAndDescription(label, description); dragCell.setLocalized(feedItem.isTranslated()); + dragCell.setCurrentDefault(feedItem.getLocale().equals(Locale.getDefault())); dragCell.setMiniLabel(mNumberFormatter.format(i + 1)); dragCell.setShowCheckbox(mRemoveMode); dragCell.setShowMiniLabel(!mRemoveMode); diff --git a/src/com/android/settings/localepicker/LocaleDragCell.java b/src/com/android/settings/localepicker/LocaleDragCell.java index ea86189b018..2f4cfefefb1 100644 --- a/src/com/android/settings/localepicker/LocaleDragCell.java +++ b/src/com/android/settings/localepicker/LocaleDragCell.java @@ -33,6 +33,7 @@ class LocaleDragCell extends RelativeLayout { private CheckBox mCheckbox; private TextView mMiniLabel; private TextView mLocalized; + private TextView mCurrentDefault; private ImageView mDragHandle; public LocaleDragCell(Context context, AttributeSet attrs) { @@ -44,6 +45,7 @@ class LocaleDragCell extends RelativeLayout { super.onFinishInflate(); mLabel = (TextView) findViewById(R.id.label); mLocalized = (TextView) findViewById(R.id.l10nWarn); + mCurrentDefault = (TextView) findViewById(R.id.default_locale); mMiniLabel = (TextView) findViewById(R.id.miniLabel); mCheckbox = (CheckBox) findViewById(R.id.checkbox); mDragHandle = (ImageView) findViewById(R.id.dragHandle); @@ -100,6 +102,14 @@ class LocaleDragCell extends RelativeLayout { invalidate(); } + /** + * Indicate current locale is system default. + */ + public void setCurrentDefault(boolean isCurrentDefault) { + mCurrentDefault.setVisibility(isCurrentDefault ? VISIBLE : GONE); + invalidate(); + } + public ImageView getDragHandle() { return mDragHandle; } diff --git a/src/com/android/settings/localepicker/LocaleHelperPreferenceController.java b/src/com/android/settings/localepicker/LocaleHelperPreferenceController.java new file mode 100644 index 00000000000..05c740139cc --- /dev/null +++ b/src/com/android/settings/localepicker/LocaleHelperPreferenceController.java @@ -0,0 +1,74 @@ +/* + * 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.localepicker; + +import android.content.Context; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settingslib.HelpUtils; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.widget.FooterPreference; + +/** + * A controller to update current locale information of application. + */ +public class LocaleHelperPreferenceController extends AbstractPreferenceController { + private static final String TAG = LocaleHelperPreferenceController.class.getSimpleName(); + + private static final String KEY_FOOTER_LANGUAGE_PICKER = "footer_languages_picker"; + + public LocaleHelperPreferenceController(Context context) { + super(context); + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_FOOTER_LANGUAGE_PICKER; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + FooterPreference footerPreference = screen.findPreference(getPreferenceKey()); + updateFooterPreference(footerPreference); + } + + @VisibleForTesting + void updateFooterPreference(FooterPreference footerPreference) { + if (footerPreference != null) { + footerPreference.setLearnMoreAction(v -> openLocaleLearnMoreLink()); + footerPreference.setLearnMoreText(mContext.getString( + R.string.desc_locale_helper_footer_general)); + } + } + + private void openLocaleLearnMoreLink() { + mContext.startActivity( + HelpUtils.getHelpIntent( + mContext, + mContext.getString(R.string.link_locale_picker_footer_learn_more), + /*backupContext=*/"")); + } +} diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java index eac2dd1df3c..9db3468c9e1 100644 --- a/src/com/android/settings/localepicker/LocaleListEditor.java +++ b/src/com/android/settings/localepicker/LocaleListEditor.java @@ -36,6 +36,7 @@ import android.widget.TextView; import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; +import androidx.preference.PreferenceScreen; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.app.LocalePicker; @@ -46,6 +47,7 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexableRaw; +import com.android.settingslib.widget.LayoutPreference; import java.util.ArrayList; import java.util.List; @@ -64,6 +66,7 @@ public class LocaleListEditor extends RestrictedSettingsFragment { private static final int REQUEST_LOCALE_PICKER = 0; private static final String INDEX_KEY_ADD_LANGUAGE = "add_language"; + private static final String KEY_LANGUAGES_PICKER = "languages_picker"; private LocaleDragAndDropAdapter mAdapter; private Menu mMenu; @@ -72,6 +75,9 @@ public class LocaleListEditor extends RestrictedSettingsFragment { private boolean mShowingRemoveDialog; private boolean mIsUiRestricted; + private LayoutPreference mLocalePickerPreference; + private LocaleHelperPreferenceController mLocaleHelperPreferenceController; + public LocaleListEditor() { super(DISALLOW_CONFIG_LOCALE); } @@ -86,6 +92,14 @@ public class LocaleListEditor extends RestrictedSettingsFragment { super.onCreate(savedInstanceState); setHasOptionsMenu(true); + addPreferencesFromResource(R.xml.languages); + final Activity activity = getActivity(); + activity.setTitle(R.string.language_picker_title); + mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(activity); + final PreferenceScreen screen = getPreferenceScreen(); + mLocalePickerPreference = screen.findPreference(KEY_LANGUAGES_PICKER); + mLocaleHelperPreferenceController.displayPreference(screen); + LocaleStore.fillCache(this.getContext()); final List feedsList = getUserLocaleList(); mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList); @@ -93,11 +107,8 @@ public class LocaleListEditor extends RestrictedSettingsFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstState) { - final View result = super.onCreateView(inflater, container, savedInstState); - final View myLayout = inflater.inflate(R.layout.locale_order_list, (ViewGroup) result); - - configureDragAndDrop(myLayout); - return result; + configureDragAndDrop(mLocalePickerPreference); + return super.onCreateView(inflater, container, savedInstState); } @Override @@ -287,8 +298,8 @@ public class LocaleListEditor extends RestrictedSettingsFragment { return result; } - private void configureDragAndDrop(View view) { - final RecyclerView list = view.findViewById(R.id.dragList); + private void configureDragAndDrop(LayoutPreference layout) { + final RecyclerView list = layout.findViewById(R.id.dragList); final LocaleLinearLayoutManager llm = new LocaleLinearLayoutManager(getContext(), mAdapter); llm.setAutoMeasureEnabled(true); list.setLayoutManager(llm); @@ -297,7 +308,7 @@ public class LocaleListEditor extends RestrictedSettingsFragment { mAdapter.setRecyclerView(list); list.setAdapter(mAdapter); - mAddLanguage = view.findViewById(R.id.add_language); + mAddLanguage = layout.findViewById(R.id.add_language); mAddLanguage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/tests/unit/src/com/android/settings/localepicker/LocaleHelperPreferenceControllerTest.java b/tests/unit/src/com/android/settings/localepicker/LocaleHelperPreferenceControllerTest.java new file mode 100644 index 00000000000..31b8e794480 --- /dev/null +++ b/tests/unit/src/com/android/settings/localepicker/LocaleHelperPreferenceControllerTest.java @@ -0,0 +1,59 @@ +/* + * 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.localepicker; + +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.os.Looper; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settingslib.widget.FooterPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +public class LocaleHelperPreferenceControllerTest { + private Context mContext; + private LocaleHelperPreferenceController mLocaleHelperPreferenceController; + + @Mock + private FooterPreference mMockFooterPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + if (Looper.myLooper() == null) { + Looper.prepare(); + } + mContext = ApplicationProvider.getApplicationContext(); + mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(mContext); + } + + @Test + public void updateFooterPreference_setFooterPreference_hasClickAction() { + mLocaleHelperPreferenceController.updateFooterPreference(mMockFooterPreference); + verify(mMockFooterPreference).setLearnMoreText(anyString()); + } +} From e6b46dc853877d07597e7fb144b12cd8940a1b26 Mon Sep 17 00:00:00 2001 From: tom hsu Date: Fri, 19 Aug 2022 15:54:53 +0800 Subject: [PATCH 2/5] [Panlingual] Remove featureflag of app language. Panlingual successfully landed. Hence, we can remove the feature flag right now. Bug: b/209775925 Test: atest pass Test: Manual test pass Change-Id: I464a206027fd63ee1763acaf17d1b6251e839bc0 --- .../AppLocalePreferenceController.java | 5 +- .../ManageAppLocalePreferenceController.java | 40 ----------- .../AppLocalePreferenceControllerTest.java | 27 +------- ...nageAppLocalePreferenceControllerTest.java | 66 ------------------- 4 files changed, 3 insertions(+), 135 deletions(-) delete mode 100644 src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceController.java delete mode 100644 tests/unit/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceControllerTest.java diff --git a/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java b/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java index f406d8763ff..6bf94a61200 100644 --- a/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java @@ -22,7 +22,6 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.text.TextUtils; -import android.util.FeatureFlagUtils; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -51,9 +50,7 @@ public class AppLocalePreferenceController extends AppInfoPreferenceControllerBa @Override public int getAvailabilityStatus() { - boolean isFeatureOn = FeatureFlagUtils - .isEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION); - return isFeatureOn && canDisplayLocaleUi() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; + return canDisplayLocaleUi() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; } @Override diff --git a/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceController.java b/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceController.java deleted file mode 100644 index aa12b626eb7..00000000000 --- a/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceController.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2021 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.applications.appinfo; - -import android.content.Context; -import android.util.FeatureFlagUtils; - -import com.android.settings.core.BasePreferenceController; - -/** - * A controller to update current locale information of application - * and a entry to launch {@link ManageApplications}. - * TODO(209775925) After feature release, this class may be removed. - */ -public class ManageAppLocalePreferenceController extends BasePreferenceController { - public ManageAppLocalePreferenceController(Context context, String key) { - super(context, key); - } - - @Override - public int getAvailabilityStatus() { - return FeatureFlagUtils - .isEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION) - ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; - } -} diff --git a/tests/unit/src/com/android/settings/applications/appinfo/AppLocalePreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/appinfo/AppLocalePreferenceControllerTest.java index 526b6cc9e3e..805041c6736 100644 --- a/tests/unit/src/com/android/settings/applications/appinfo/AppLocalePreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/applications/appinfo/AppLocalePreferenceControllerTest.java @@ -19,7 +19,6 @@ package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; import android.content.Context; -import android.util.FeatureFlagUtils; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -49,22 +48,10 @@ public class AppLocalePreferenceControllerTest { return mCanDisplayLocaleUi; } }; - FeatureFlagUtils - .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, true); } @Test - public void getAvailabilityStatus_canShowUiButFeatureFlagOff_shouldReturnUnavailable() { - mCanDisplayLocaleUi = true; - FeatureFlagUtils - .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, false); - - assertThat(mController.getAvailabilityStatus()) - .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); - } - - @Test - public void getAvailabilityStatus_canShowUiAndFeatureFlagOn_shouldReturnAvailable() { + public void getAvailabilityStatus_canShowUi_shouldReturnAvailable() { mCanDisplayLocaleUi = true; assertThat(mController.getAvailabilityStatus()) @@ -72,20 +59,10 @@ public class AppLocalePreferenceControllerTest { } @Test - public void getAvailabilityStatus_featureFlagOnButCanNotShowUi_shouldReturnUnavailable() { + public void getAvailabilityStatus_canNotShowUi_shouldReturnUnavailable() { mCanDisplayLocaleUi = false; assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); } - - @Test - public void getAvailabilityStatus_featureFlagOffAndCanNotShowUi_shouldReturnUnavailable() { - mCanDisplayLocaleUi = false; - FeatureFlagUtils - .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, false); - - assertThat(mController.getAvailabilityStatus()) - .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); - } } diff --git a/tests/unit/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceControllerTest.java deleted file mode 100644 index 648c7570304..00000000000 --- a/tests/unit/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceControllerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2021 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.applications.appinfo; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.spy; - -import android.content.Context; -import android.util.FeatureFlagUtils; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; - - -import com.android.settings.core.BasePreferenceController; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -public class ManageAppLocalePreferenceControllerTest { - private Context mContext; - private ManageAppLocalePreferenceController mController; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = spy(ApplicationProvider.getApplicationContext()); - mController = spy(new ManageAppLocalePreferenceController(mContext, "a key")); - - FeatureFlagUtils - .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, true); - } - - @Test - public void getAvailabilityStatus_featureFlagOff_shouldReturnUnavailable() { - FeatureFlagUtils - .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, false); - - assertThat(mController.getAvailabilityStatus()) - .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); - } - - @Test - public void getAvailabilityStatus_featureFlagOn_shouldReturnAvailable() { - assertThat(mController.getAvailabilityStatus()) - .isEqualTo(BasePreferenceController.AVAILABLE); - } -} From 3aa4440b364da62627fd5677848e2d26b8b3c9d1 Mon Sep 17 00:00:00 2001 From: tom hsu Date: Fri, 19 Aug 2022 15:12:50 +0800 Subject: [PATCH 3/5] [Panlingual] Improve conditions of supporting app locale. There are 3 conditions we need to check. 1. Has locale config file 2. Has locale config file w/o content 3. Has locale config file w/ content Currently, we do not have condition 2 into the condition group, and we need to add it into. Bug: b/243099750 Test: Manual Change-Id: I58d0275af53031ba4f4c705022017d5143f45795 --- src/com/android/settings/applications/AppLocaleUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/applications/AppLocaleUtil.java b/src/com/android/settings/applications/AppLocaleUtil.java index 8c3671ed943..79406f05224 100644 --- a/src/com/android/settings/applications/AppLocaleUtil.java +++ b/src/com/android/settings/applications/AppLocaleUtil.java @@ -100,8 +100,8 @@ public class AppLocaleUtil { */ public static boolean isAppLocaleSupported(Context context, String packageName) { LocaleList localeList = getPackageLocales(context, packageName); - if (localeList != null && localeList.size() > 0) { - return true; + if (localeList != null) { + return localeList.size() > 0; } if (FeatureFlagUtils.isEnabled( From 7a4ddb83377fa04caaa6c660a849f99c4814dee4 Mon Sep 17 00:00:00 2001 From: lbill Date: Wed, 24 Aug 2022 13:37:11 +0000 Subject: [PATCH 4/5] Set appropriate theme for SkipFingerprintDialog The SkipFingerprintDialog is instantiation in SetupFingerprintEnrollFindSensor#onSkipButtonClick() Due to the call flow did not set appropriate theme defined in setuplib for skip alertDialog instance we set GlifV2ThemeAlertDialog AlertDialog.Builder. Test: m RunSettingsRoboTests -j30 ROBOTEST_FILTER= \ SetupFingerprintEnrollFindSensorTest Test: manual factory reset, go through SUW, and check skip AlertDialog Bottom Bar Buttons visual. Bug: 233243999 Change-Id: Ic198a23eb3e76d70e287b24f2ab1ef249b30b2fc --- .../SetupFingerprintEnrollFindSensor.java | 2 +- .../SetupFingerprintEnrollFindSensorTest.java | 23 +++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java index 7256511d2e6..1ae5daee348 100644 --- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java +++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java @@ -77,7 +77,7 @@ public class SetupFingerprintEnrollFindSensor extends FingerprintEnrollFindSenso @NonNull public AlertDialog.Builder onCreateDialogBuilder() { - return new AlertDialog.Builder(getContext()) + return new AlertDialog.Builder(getActivity(), R.style.GlifV2ThemeAlertDialog) .setTitle(R.string.setup_fingerprint_enroll_skip_title) .setPositiveButton(R.string.skip_anyway_button_label, this) .setNegativeButton(R.string.go_back_button_label, this) diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java index a198d86a814..54a7fb16eb6 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java @@ -22,7 +22,6 @@ import static org.robolectric.RuntimeEnvironment.application; import android.content.Intent; import android.hardware.fingerprint.FingerprintManager; -import android.widget.Button; import androidx.appcompat.app.AlertDialog; @@ -66,6 +65,23 @@ public class SetupFingerprintEnrollFindSensorTest { @Test public void fingerprintEnroll_showsAlert_whenClickingSkip() { + final AlertDialog alertDialog = setupAlertDialog(); + final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf( + alertDialog); + final int titleRes = R.string.setup_fingerprint_enroll_skip_title; + + assertThat(application.getString(titleRes)).isEqualTo(shadowAlertDialog.getTitle()); + } + + @Test + public void fingerprintEnroll_showsAlert_setSudTheme() { + final AlertDialog alertDialog = setupAlertDialog(); + + assertThat(alertDialog.getContext().getThemeResId()).isEqualTo( + R.style.GlifV2ThemeAlertDialog); + } + + private AlertDialog setupAlertDialog() { final Intent intent = new Intent() // Set the challenge token so the confirm screen will not be shown .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]); @@ -80,9 +96,6 @@ public class SetupFingerprintEnrollFindSensorTest { final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog(); assertThat(alertDialog).isNotNull(); - final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf( - alertDialog); - final int titleRes = R.string.setup_fingerprint_enroll_skip_title; - assertThat(application.getString(titleRes)).isEqualTo(shadowAlertDialog.getTitle()); + return alertDialog; } } From 54c677a83c2488d577a047199234d4a152a73acf Mon Sep 17 00:00:00 2001 From: Chloris Kuo Date: Tue, 16 Aug 2022 15:08:29 -0700 Subject: [PATCH 5/5] Support ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS in Enhanced Notifications Show detail settings page from the default NAS app if it implements the new intent ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS. Test: Robotest, manually test on device Bug: 231492005 Change-Id: I6566cd9d615331a56728613583295637982bcd3f Merged-In: I6566cd9d615331a56728613583295637982bcd3f --- res/xml/configure_notification_settings.xml | 2 +- ...ficationAssistantPreferenceController.java | 56 +++++++++++++- ...tionAssistantPreferenceControllerTest.java | 74 ++++++++++++++++++- 3 files changed, 125 insertions(+), 7 deletions(-) diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml index 4e58e66887d..96a3f85a46a 100644 --- a/res/xml/configure_notification_settings.xml +++ b/res/xml/configure_notification_settings.xml @@ -156,7 +156,7 @@ android:title="@string/notification_pulse_title" settings:controller="com.android.settings.notification.PulseNotificationPreferenceController"/> - resolved = mPackageManager.queryIntentActivities(mNASSettingIntent, + PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_ALL)); + return (resolved != null && !resolved.isEmpty()); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (isNASSettingActivityAvailable()) { + preference.setIntent(mNASSettingIntent); + } else { + // Cannot find settings activity from the default NAS app + preference.setIntent(null); + preference.setOnPreferenceClickListener( + preference1 -> { + onPreferenceChange(preference1, !isChecked()); + ((PrimarySwitchPreference) preference1).setChecked(isChecked()); + return true; + } + ); + } + } } diff --git a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java index d1307114e65..b5946673815 100644 --- a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java @@ -16,7 +16,12 @@ package com.android.settings.notification; +import static android.service.notification.NotificationAssistantService.ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS; + +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -29,16 +34,24 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.Application; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.os.UserManager; import android.provider.Settings; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.testutils.shadow.ShadowSecureSettings; +import com.android.settingslib.PrimarySwitchPreference; import org.junit.Before; import org.junit.Test; @@ -47,9 +60,13 @@ import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; +import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; +import java.util.ArrayList; +import java.util.List; + @RunWith(RobolectricTestRunner.class) public class NotificationAssistantPreferenceControllerTest { @@ -67,23 +84,48 @@ public class NotificationAssistantPreferenceControllerTest { private NotificationBackend mBackend; @Mock private UserManager mUserManager; + @Mock + private PackageManager mPackageManager; private NotificationAssistantPreferenceController mPreferenceController; - ComponentName mNASComponent = new ComponentName("a", "b"); + ComponentName mNASComponent = new ComponentName("pkgname", "clsname"); + private PrimarySwitchPreference mPreference; + private ShadowApplication mShadowApplication; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); - ShadowApplication.getInstance().setSystemService(Context.USER_SERVICE, mUserManager); + mPreference = spy(new PrimarySwitchPreference(mContext)); + mShadowApplication = ShadowApplication.getInstance(); + mShadowApplication.setSystemService(Context.USER_SERVICE, mUserManager); doReturn(mContext).when(mFragment).getContext(); when(mFragment.getFragmentManager()).thenReturn(mFragmentManager); when(mFragmentManager.beginTransaction()).thenReturn(mFragmentTransaction); when(mBackend.getDefaultNotificationAssistant()).thenReturn(mNASComponent); + when(mContext.getPackageManager()).thenReturn(mPackageManager); mPreferenceController = new NotificationAssistantPreferenceController(mContext); mPreferenceController.setBackend(mBackend); mPreferenceController.setFragment(mFragment); + mPreferenceController.getDefaultNASIntent(); + + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); + mPreference.setKey(NotificationAssistantPreferenceController.KEY_NAS); + screen.addPreference(mPreference); + mPreferenceController.displayPreference(screen); + when(mUserManager.getProfileIds(eq(0), anyBoolean())).thenReturn(new int[] {0, 10}); when(mUserManager.getProfileIds(eq(20), anyBoolean())).thenReturn(new int[] {20}); + + ActivityInfo activityInfo1 = new ActivityInfo(); + activityInfo1.packageName = "pkgname"; + activityInfo1.name = "name"; + ResolveInfo resolveInfo1 = new ResolveInfo(); + resolveInfo1.activityInfo = activityInfo1; + List resolvers1 = new ArrayList<>(); + resolvers1.add(resolveInfo1); + when(mPackageManager.queryIntentActivities(any(Intent.class), any())) + .thenReturn(resolvers1); } @Test @@ -108,6 +150,34 @@ public class NotificationAssistantPreferenceControllerTest { verify(mBackend, times(1)).setNotificationAssistantGranted(null); } + @Test + public void testUpdateState_SettingActivityAvailable() throws Exception { + mPreferenceController.updateState(mPreference); + assertNotNull(mPreference.getIntent()); + + mPreference.performClick(); + Intent nextIntent = Shadows.shadowOf( + (Application) ApplicationProvider.getApplicationContext()).getNextStartedActivity(); + assertEquals(nextIntent.getAction(), ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS); + } + + @Test + public void testUpdateState_SettingActivityUnavailable() throws Exception { + when(mPackageManager.queryIntentActivities(any(Intent.class), any())) + .thenReturn(null); + mPreferenceController.updateState(mPreference); + assertNull(mPreference.getIntent()); + + mPreference.performClick(); + Intent nextIntent = Shadows.shadowOf( + (Application) ApplicationProvider.getApplicationContext()).getNextStartedActivity(); + assertNull(nextIntent); + // Verify a dialog is shown + verify(mFragmentTransaction).add( + any(NotificationAssistantDialogFragment.class), anyString()); + verify(mBackend, times(0)).setNotificationAssistantGranted(any()); + } + @Test @Config(shadows = ShadowSecureSettings.class) public void testMigrationFromSetting_userEnable_multiProfile() throws Exception {