Merge "Reduce jank when revoking notification permission" into udc-dev
diff --git a/res/drawable/ic_important_outline.xml b/res/drawable/ic_important_outline.xml
index 7a628bb..642582c 100644
--- a/res/drawable/ic_important_outline.xml
+++ b/res/drawable/ic_important_outline.xml
@@ -20,6 +20,7 @@
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
+ android:autoMirrored="true"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index e55c1e6..0d5ccfb 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -20,6 +20,7 @@
android:id="@+id/panel_container"
android:layout_width="@dimen/settings_panel_width"
android:layout_height="wrap_content"
+ android:fitsSystemWindows="true"
android:layout_gravity="center_horizontal"
android:background="@drawable/settings_panel_rounded_top_corner_background" >
diff --git a/res/layout/zen_mode_senders_overlay_image.xml b/res/layout/zen_mode_senders_overlay_image.xml
deleted file mode 100644
index eba98da..0000000
--- a/res/layout/zen_mode_senders_overlay_image.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <RelativeLayout android:id="@+id/zen_mode_settings_senders_overlay_view"
- android:layout_centerInParent="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/zen_conversations_image_margin_vertical"
- android:layout_marginBottom="@dimen/zen_conversations_image_margin_vertical">
- </RelativeLayout>
-</RelativeLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 57e47f2..2f3d875 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -51,9 +51,6 @@
<dimen name="conversation_icon_size">32dp</dimen>
<dimen name="zen_mode_settings_button_margin_vertical">24dp</dimen>
- <dimen name="zen_conversations_image_margin_vertical">24dp</dimen>
- <dimen name="zen_conversations_icon_offset">32dp</dimen>
- <dimen name="zen_conversations_icon_size">50dp</dimen>
<dimen name="zen_schedule_rule_checkbox_padding">7dp</dimen>
<dimen name="zen_schedule_day_margin">17dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4ae9e67..a5b1aa1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8177,8 +8177,6 @@
<!-- [CHAR LIMIT=120] Zen mode settings: Title for conversations settings page -->
<string name="zen_mode_conversations_title">Conversations</string>
- <!-- [CHAR LIMIT=120] Zen mode settings: Header for conversations settings page -->
- <string name="zen_mode_conversations_section_title">Conversations that can interrupt</string>
<string name="zen_mode_from_all_conversations">All conversations</string>
<string name="zen_mode_from_important_conversations">Priority conversations</string>
<!-- [CHAR LIMIT=40] Version of the above for "priority conversations" when it is a non-first member of a list -->
@@ -11698,6 +11696,10 @@
<string name="dream_complications_toggle_title">Show additional information</string>
<!-- The summary of what overlays this toggle controls [CHAR LIMIT=none] -->
<string name="dream_complications_toggle_summary">Display things like the time, weather, or other information on the screen saver</string>
+ <!-- The title of the toggle which enables/disables the home controls button on top of the screen saver [CHAR LIMIT=none] -->
+ <string name="dream_home_controls_toggle_title">Show home controls</string>
+ <!-- The summary of the home controls toggle [CHAR LIMIT=none] -->
+ <string name="dream_home_controls_toggle_summary">Show home controls button from the screen saver</string>
<!-- The title of the category to show for the screensaver miscellaneous settings [CHAR LIMIT=none] -->
<string name="dream_more_settings_category">More settings</string>
<!-- The title of the screen saver setup page [CHAR LIMIT=none] -->
diff --git a/res/values/themes.xml b/res/values/themes.xml
index dd3882e..eeba1c7 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -220,6 +220,7 @@
<!-- Note that Dialog themes do not set list dividers -->
<style name="Theme.Panel" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
<item name="android:windowBackground">@null</item>
+ <item name="android:windowTranslucentNavigation">true</item>
<item name="android:dividerHorizontal">@*android:drawable/list_divider_material</item>
<item name="android:windowNoTitle">true</item>
<item name="android:listDivider">@*android:drawable/list_divider_material</item>
diff --git a/res/xml/dream_fragment_overview.xml b/res/xml/dream_fragment_overview.xml
index 3321fd1..8377a06 100644
--- a/res/xml/dream_fragment_overview.xml
+++ b/res/xml/dream_fragment_overview.xml
@@ -46,6 +46,12 @@
android:summary="@string/dream_complications_toggle_summary"
settings:controller="com.android.settings.dream.DreamComplicationPreferenceController"/>
+ <SwitchPreference
+ android:key="dream_home_controls_toggle"
+ android:title="@string/dream_home_controls_toggle_title"
+ android:summary="@string/dream_home_controls_toggle_summary"
+ settings:controller="com.android.settings.dream.DreamHomeControlsPreferenceController"/>
+
<com.android.settings.applications.SpacePreference
android:layout_height="16dp" />
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index 69fa4d2..ff41a0b 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -37,5 +37,13 @@
android:name="classname"
android:value="com.android.settings.applications.appinfo.AppLocaleDetails" />
</Preference>
+
+ <Preference
+ android:key="regional_preferences"
+ android:title="@string/regional_preferences_title"
+ android:summary="@string/regional_preferences_summary"
+ android:fragment="com.android.settings.regionalpreferences.RegionalPreferencesEntriesFragment"
+ settings:controller="com.android.settings.regionalpreferences.RegionalPreferencesController" />
+
</PreferenceCategory>
</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/zen_mode_conversations_settings.xml b/res/xml/zen_mode_conversations_settings.xml
deleted file mode 100644
index e72d03c..0000000
--- a/res/xml/zen_mode_conversations_settings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:key="zen_mode_conversations_settings"
- android:title="@string/zen_mode_conversations_title">
- <!-- Conversations -->
- <PreferenceCategory
- android:key="zen_mode_conversations_radio_buttons"
- android:title="@string/zen_mode_conversations_section_title">
-
- <!-- Senders image -->
- <com.android.settingslib.widget.LayoutPreference
- android:key="zen_mode_conversations_image"
- android:layout="@layout/zen_mode_senders_overlay_image"
- android:selectable="false"/>
- </PreferenceCategory>
-</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
index 85783b73..4641a15 100644
--- a/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
@@ -18,6 +18,7 @@
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
+import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
@@ -72,8 +73,7 @@
@Override
public int getMetricsCategory() {
- // TODO(b/262839191): To be updated settings_enums.proto
- return 0;
+ return SettingsEnums.ACCESSIBILITY_HEARING_AID_SETTINGS;
}
@Override
diff --git a/src/com/android/settings/accessibility/FlashNotificationsPreferenceFragment.java b/src/com/android/settings/accessibility/FlashNotificationsPreferenceFragment.java
index f35d1a1..f796474 100644
--- a/src/com/android/settings/accessibility/FlashNotificationsPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/FlashNotificationsPreferenceFragment.java
@@ -16,6 +16,7 @@
package com.android.settings.accessibility;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import com.android.settings.R;
@@ -41,8 +42,7 @@
@Override
public int getMetricsCategory() {
- // TODO: Flash notifications have to add SettingsEnums.
- return 0;
+ return SettingsEnums.FLASH_NOTIFICATION_SETTINGS;
}
@Override
diff --git a/src/com/android/settings/accessibility/HearingDevicePairingDetail.java b/src/com/android/settings/accessibility/HearingDevicePairingDetail.java
index aa9b587..35997dd 100644
--- a/src/com/android/settings/accessibility/HearingDevicePairingDetail.java
+++ b/src/com/android/settings/accessibility/HearingDevicePairingDetail.java
@@ -16,6 +16,7 @@
package com.android.settings.accessibility;
+import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.le.ScanFilter;
@@ -61,8 +62,7 @@
@Override
public int getMetricsCategory() {
- // TODO(b/262839191): To be updated settings_enums.proto
- return 0;
+ return SettingsEnums.HEARING_AID_PAIRING;
}
@Override
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index f8c1f64..8621e6f 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -24,7 +24,9 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
import android.credentials.CredentialManager;
import android.credentials.CredentialProviderInfo;
import android.credentials.SetEnabledProvidersException;
@@ -32,6 +34,7 @@
import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -162,10 +165,54 @@
PreferenceGroup group = screen.findPreference(getPreferenceKey());
Context context = screen.getContext();
+ mPrefs.putAll(buildPreferenceList(context, group));
+ }
- for (CredentialProviderInfo service : mServices) {
- group.addPreference(createPreference(context, service));
+ /** Aggregates the list of services and builds a list of UI prefs to show. */
+ @VisibleForTesting
+ public Map<String, SwitchPreference> buildPreferenceList(
+ Context context, PreferenceGroup group) {
+ // Group the services by package name.
+ Map<String, List<CredentialProviderInfo>> groupedInfos = new HashMap<>();
+ for (CredentialProviderInfo cpi : mServices) {
+ String packageName = cpi.getServiceInfo().packageName;
+ if (!groupedInfos.containsKey(packageName)) {
+ groupedInfos.put(packageName, new ArrayList<>());
+ }
+
+ groupedInfos.get(packageName).add(cpi);
}
+
+ // Build the pref list.
+ Map<String, SwitchPreference> output = new HashMap<>();
+ for (String packageName : groupedInfos.keySet()) {
+ List<CredentialProviderInfo> infos = groupedInfos.get(packageName);
+ CredentialProviderInfo firstInfo = infos.get(0);
+ ServiceInfo firstServiceInfo = firstInfo.getServiceInfo();
+ CharSequence title = firstInfo.getLabel(context);
+ Drawable icon = firstInfo.getServiceIcon(context);
+
+ if (infos.size() > 1) {
+ // If there is more than one then group them under the package.
+ ApplicationInfo appInfo = firstServiceInfo.applicationInfo;
+ if (appInfo.nonLocalizedLabel != null) {
+ title = appInfo.loadLabel(mPm);
+ }
+ icon = mIconFactory.getBadgedIcon(appInfo, getUser());
+ }
+
+ // If there is no title then don't show anything.
+ if (TextUtils.isEmpty(title)) {
+ continue;
+ }
+
+ // Build the pref and add it to the output & group.
+ SwitchPreference pref = addProviderPreference(context, title, icon, packageName);
+ output.put(packageName, pref);
+ group.addPreference(pref);
+ }
+
+ return output;
}
/** Creates a preference object based on the provider info. */
@@ -238,7 +285,6 @@
final SwitchPreference pref = new SwitchPreference(prefContext);
pref.setTitle(title);
pref.setChecked(mEnabledPackageNames.contains(packageName));
- mPrefs.put(packageName, pref);
if (icon != null) {
pref.setIcon(Utils.getSafeIcon(icon));
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java b/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java
index ea89053..6c435a2 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java
@@ -20,6 +20,7 @@
import static com.android.settings.bluetooth.BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS;
+import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.util.Log;
@@ -32,10 +33,8 @@
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.search.SearchIndexable;
/** Settings fragment containing bluetooth audio routing. */
-@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class BluetoothDetailsAudioRoutingFragment extends RestrictedDashboardFragment {
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
@@ -73,8 +72,7 @@
@Override
public int getMetricsCategory() {
- // TODO(b/262839191): To be updated settings_enums.proto
- return 0;
+ return SettingsEnums.BLUETOOTH_AUDIO_ROUTING;
}
@Override
diff --git a/src/com/android/settings/dream/DreamHomeControlsPreferenceController.java b/src/com/android/settings/dream/DreamHomeControlsPreferenceController.java
new file mode 100644
index 0000000..b39f3b1
--- /dev/null
+++ b/src/com/android/settings/dream/DreamHomeControlsPreferenceController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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.dream;
+
+import android.content.Context;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.dream.DreamBackend;
+
+/**
+ * Controller for the {@link androidx.preference.SwitchPreference} which controls if dream
+ * overlays should be enabled.
+ */
+public class DreamHomeControlsPreferenceController extends TogglePreferenceController {
+ private final DreamBackend mBackend;
+
+ public DreamHomeControlsPreferenceController(Context context, String key) {
+ this(context, key, DreamBackend.getInstance(context));
+ }
+
+ @VisibleForTesting
+ public DreamHomeControlsPreferenceController(Context context, String key,
+ DreamBackend dreamBackend) {
+ super(context, key);
+ mBackend = dreamBackend;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ final boolean supported =
+ mBackend.getSupportedComplications()
+ .contains(DreamBackend.COMPLICATION_TYPE_HOME_CONTROLS);
+ return supported ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mBackend.getEnabledComplications().contains(
+ DreamBackend.COMPLICATION_TYPE_HOME_CONTROLS);
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ mBackend.setHomeControlsEnabled(isChecked);
+ return true;
+ }
+
+ @Override
+ public int getSliceHighlightMenuRes() {
+ return R.string.menu_key_display;
+ }
+}
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
index 2db3382..0f49ee1 100644
--- a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
@@ -37,10 +37,10 @@
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.inputmethod.NewKeyboardSettingsUtils.KeyboardInfo;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import java.util.Locale;
-import java.util.Map;
public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
implements InputManager.InputDeviceListener {
@@ -53,7 +53,7 @@
private int mUserId;
private int mInputDeviceId;
private Context mContext;
- private Map<String, KeyboardInfo> mKeyboardLanguageLayouts = new HashMap<>();
+ private ArrayList<KeyboardInfo> mKeyboardInfoList = new ArrayList<>();
@Override
public void onActivityCreated(final Bundle icicle) {
@@ -74,8 +74,16 @@
PreferenceScreen preferenceScreen = getPreferenceScreen();
preferenceScreen.removeAll();
List<InputMethodInfo> infoList = mImm.getEnabledInputMethodListAsUser(mUserId);
+ Collections.sort(infoList, new Comparator<InputMethodInfo>() {
+ public int compare(InputMethodInfo o1, InputMethodInfo o2) {
+ String s1 = o1.loadLabel(mContext.getPackageManager()).toString();
+ String s2 = o2.loadLabel(mContext.getPackageManager()).toString();
+ return s1.compareTo(s2);
+ }
+ });
+
for (InputMethodInfo info : infoList) {
- mKeyboardLanguageLayouts.clear();
+ mKeyboardInfoList.clear();
List<InputMethodSubtype> subtypes =
mImm.getEnabledInputMethodSubtypeList(info, true);
for (InputMethodSubtype subtype : subtypes) {
@@ -88,51 +96,58 @@
}
private void mapLanguageWithLayout(InputMethodInfo info, InputMethodSubtype subtype) {
+ CharSequence subtypeLabel = getSubtypeLabel(mContext, info, subtype);
KeyboardLayout[] keyboardLayouts = getKeyboardLayouts(info, subtype);
String layout = getKeyboardLayout(info, subtype);
- String language = getLanguage(info, subtype);
+
if (layout != null) {
for (int i = 0; i < keyboardLayouts.length; i++) {
if (keyboardLayouts[i].getDescriptor().equals(layout)) {
KeyboardInfo keyboardInfo = new KeyboardInfo(
- language,
+ subtypeLabel,
keyboardLayouts[i].getLabel(),
info,
subtype);
- mKeyboardLanguageLayouts.put(subtype.getLanguageTag(), keyboardInfo);
+ mKeyboardInfoList.add(keyboardInfo);
break;
}
}
} else {
// if there is no auto-selected layout, we should show "Default"
KeyboardInfo keyboardInfo = new KeyboardInfo(
- language,
+ subtypeLabel,
mContext.getString(R.string.keyboard_default_layout),
info,
subtype);
- mKeyboardLanguageLayouts.put(subtype.getLanguageTag(), keyboardInfo);
+ mKeyboardInfoList.add(keyboardInfo);
}
}
private void updatePreferenceLayout(PreferenceScreen preferenceScreen, InputMethodInfo info) {
- if (mKeyboardLanguageLayouts.isEmpty()) {
+ if (mKeyboardInfoList.isEmpty()) {
return;
}
PreferenceCategory preferenceCategory = new PreferenceCategory(mContext);
- preferenceCategory.setTitle(info.loadLabel(mContext.getPackageManager()).toString());
+ preferenceCategory.setTitle(info.loadLabel(mContext.getPackageManager()));
preferenceCategory.setKey(info.getPackageName());
preferenceScreen.addPreference(preferenceCategory);
- for (Map.Entry<String, KeyboardInfo> entry : mKeyboardLanguageLayouts.entrySet()) {
+ Collections.sort(mKeyboardInfoList, new Comparator<KeyboardInfo>() {
+ public int compare(KeyboardInfo o1, KeyboardInfo o2) {
+ String s1 = o1.getSubtypeLabel().toString();
+ String s2 = o2.getSubtypeLabel().toString();
+ return s1.compareTo(s2);
+ }
+ });
+
+ for (KeyboardInfo keyboardInfo : mKeyboardInfoList) {
final Preference pref = new Preference(mContext);
- String key = "keyboard_language_" + entry.getKey();
- NewKeyboardSettingsUtils.KeyboardInfo keyboardInfo = entry.getValue();
- pref.setKey(key);
- pref.setTitle(keyboardInfo.getLanguage());
+ pref.setKey(keyboardInfo.getPrefId());
+ pref.setTitle(keyboardInfo.getSubtypeLabel());
pref.setSummary(keyboardInfo.getLayout());
pref.setOnPreferenceClickListener(
preference -> {
showKeyboardLayoutPicker(
- keyboardInfo.getLanguage(),
+ keyboardInfo.getSubtypeLabel(),
keyboardInfo.getLayout(),
mInputDeviceIdentifier,
mUserId,
@@ -215,7 +230,7 @@
}
private void showKeyboardLayoutPicker(
- String language,
+ CharSequence subtypeLabel,
String layout,
InputDeviceIdentifier inputDeviceIdentifier,
int userId,
@@ -229,7 +244,7 @@
arguments.putParcelable(
NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE, inputMethodSubtype);
arguments.putInt(NewKeyboardSettingsUtils.EXTRA_USER_ID, userId);
- arguments.putString(NewKeyboardSettingsUtils.EXTRA_TITLE, language);
+ arguments.putCharSequence(NewKeyboardSettingsUtils.EXTRA_TITLE, subtypeLabel);
arguments.putString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_LAYOUT, layout);
new SubSettingLauncher(mContext)
.setSourceMetricsCategory(getMetricsCategory())
@@ -248,16 +263,9 @@
mInputDeviceIdentifier, mUserId, info, subtype);
}
- private String getLanguage(InputMethodInfo info, InputMethodSubtype subtype) {
- String language;
- if (subtype.getLanguageTag().isEmpty()) {
- language = subtype.getDisplayName(
- mContext,
- info.getPackageName(),
- info.getServiceInfo().applicationInfo).toString();
- } else {
- language = Locale.forLanguageTag(subtype.getLanguageTag()).getDisplayName();
- }
- return language;
+ private CharSequence getSubtypeLabel(
+ Context context, InputMethodInfo info, InputMethodSubtype subtype) {
+ return subtype.getDisplayName(
+ context, info.getPackageName(), info.getServiceInfo().applicationInfo);
}
}
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java
index 605095f..761e95e 100644
--- a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java
@@ -36,7 +36,7 @@
super.onAttach(context);
InputManager inputManager = getContext().getSystemService(InputManager.class);
Bundle arguments = getArguments();
- final String title = arguments.getString(NewKeyboardSettingsUtils.EXTRA_TITLE);
+ final CharSequence title = arguments.getCharSequence(NewKeyboardSettingsUtils.EXTRA_TITLE);
final String layout = arguments.getString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_LAYOUT);
final int userId = arguments.getInt(NewKeyboardSettingsUtils.EXTRA_USER_ID);
final InputDeviceIdentifier identifier =
diff --git a/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java b/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java
index dda5500..506d1e7 100644
--- a/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java
+++ b/src/com/android/settings/inputmethod/NewKeyboardSettingsUtils.java
@@ -72,24 +72,28 @@
}
static class KeyboardInfo {
- String mLanguage;
+ CharSequence mSubtypeLabel;
String mLayout;
InputMethodInfo mInputMethodInfo;
InputMethodSubtype mInputMethodSubtype;
KeyboardInfo(
- String language,
+ CharSequence subtypeLabel,
String layout,
InputMethodInfo inputMethodInfo,
InputMethodSubtype inputMethodSubtype) {
- mLanguage = language;
+ mSubtypeLabel = subtypeLabel;
mLayout = layout;
mInputMethodInfo = inputMethodInfo;
mInputMethodSubtype = inputMethodSubtype;
}
- String getLanguage() {
- return mLanguage;
+ String getPrefId() {
+ return mInputMethodInfo.getId() + "_" + mInputMethodSubtype.hashCode();
+ }
+
+ CharSequence getSubtypeLabel() {
+ return mSubtypeLabel;
}
String getLayout() {
diff --git a/src/com/android/settings/language/LanguagePreferenceController.java b/src/com/android/settings/language/LanguagePreferenceController.java
index 08033cd..cbccb00 100644
--- a/src/com/android/settings/language/LanguagePreferenceController.java
+++ b/src/com/android/settings/language/LanguagePreferenceController.java
@@ -16,12 +16,22 @@
package com.android.settings.language;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.util.FeatureFlagUtils;
+import com.android.settings.Settings;
import com.android.settings.core.BasePreferenceController;
+/**
+ * This is a display controller for new language activity entry.
+ * TODO(b/273642892): When new layout is on board, this class shall be removed.
+ */
public class LanguagePreferenceController extends BasePreferenceController {
+ private static final String TAG = LanguagePreferenceController.class.getSimpleName();
+
+ private boolean mCacheIsFeatureOn = false;
public LanguagePreferenceController(Context context, String key) {
super(context, key);
@@ -31,6 +41,27 @@
public int getAvailabilityStatus() {
boolean isFeatureOn = FeatureFlagUtils
.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
+
+ // LanguageSettingsActivity is a new entry page for new language layout.
+ // LanguageAndInputSettingsActivity is existed entry page for current language layout.
+ if (mCacheIsFeatureOn != isFeatureOn) {
+ setActivityEnabled(
+ mContext, Settings.LanguageAndInputSettingsActivity.class, !isFeatureOn);
+ setActivityEnabled(mContext, Settings.LanguageSettingsActivity.class, isFeatureOn);
+ mCacheIsFeatureOn = isFeatureOn;
+ }
return isFeatureOn ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
+
+ private static void setActivityEnabled(Context context, Class klass, final boolean isEnabled) {
+ PackageManager packageManager = context.getPackageManager();
+
+ ComponentName componentName =
+ new ComponentName(context, klass);
+ final int flag = isEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+
+ packageManager.setComponentEnabledSetting(
+ componentName, flag, PackageManager.DONT_KILL_APP);
+ }
}
\ No newline at end of file
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index d5b2c2e..a9c9218 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -272,7 +272,7 @@
use(OpenNetworkSelectPagePreferenceController.class).init(mSubId);
final AutoSelectPreferenceController autoSelectPreferenceController =
use(AutoSelectPreferenceController.class)
- .init(mSubId)
+ .init(getLifecycle(), mSubId)
.addListener(openNetworkSelectPagePreferenceController);
use(NetworkPreferenceCategoryController.class).init(mSubId)
.setChildren(Arrays.asList(autoSelectPreferenceController));
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
index 72d9e91..f46a452 100644
--- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
+++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
@@ -34,8 +34,10 @@
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
@@ -45,6 +47,7 @@
import com.android.settings.R;
import com.android.settings.network.AllowedNetworkTypesListener;
import com.android.settings.network.CarrierConfigCache;
+import com.android.settings.network.helper.ServiceStateStatus;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.network.telephony.TelephonyTogglePreferenceController;
import com.android.settingslib.utils.ThreadUtils;
@@ -62,6 +65,9 @@
public class AutoSelectPreferenceController extends TelephonyTogglePreferenceController
implements LifecycleObserver{
private static final long MINIMUM_DIALOG_TIME_MILLIS = TimeUnit.SECONDS.toMillis(1);
+ private static final String LOG_TAG = "AutoSelectPreferenceController";
+ private static final String INTERNAL_LOG_TAG_INIT = "Init";
+ private static final String INTERNAL_LOG_TAG_AFTERSET = "AfterSet";
private final Handler mUiHandler;
private PreferenceScreen mPreferenceScreen;
@@ -76,6 +82,7 @@
private AtomicBoolean mUpdatingConfig;
private int mCacheOfModeStatus;
private AtomicLong mRecursiveUpdate;
+ ServiceStateStatus mServiceStateStatus;
public AutoSelectPreferenceController(Context context, String key) {
super(context, key);
@@ -129,12 +136,6 @@
@Override
public boolean isChecked() {
- if (!mUpdatingConfig.get()) {
- mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode();
- for (OnNetworkSelectModeListener lsn : mListeners) {
- lsn.onNetworkSelectModeUpdated(mCacheOfModeStatus);
- }
- }
return mCacheOfModeStatus == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
}
@@ -197,12 +198,22 @@
//Update UI in UI thread
final long durationMillis = SystemClock.elapsedRealtime() - startMillis;
+
mUiHandler.postDelayed(() -> {
- mRecursiveUpdate.getAndIncrement();
- mSwitchPreference.setEnabled(true);
- mSwitchPreference.setChecked(isChecked());
- mRecursiveUpdate.decrementAndGet();
- dismissProgressBar();
+ ThreadUtils.postOnBackgroundThread(() -> {
+ queryNetworkSelectionMode(INTERNAL_LOG_TAG_AFTERSET);
+
+ //Update UI in UI thread
+ mUiHandler.post(() -> {
+ mRecursiveUpdate.getAndIncrement();
+ if (mSwitchPreference != null) {
+ mSwitchPreference.setEnabled(true);
+ mSwitchPreference.setChecked(isChecked());
+ }
+ mRecursiveUpdate.decrementAndGet();
+ dismissProgressBar();
+ });
+ });
}, Math.max(MINIMUM_DIALOG_TIME_MILLIS - durationMillis, 0));
});
}
@@ -210,7 +221,7 @@
/**
* Initialization based on given subscription id.
**/
- public AutoSelectPreferenceController init(int subId) {
+ public AutoSelectPreferenceController init(Lifecycle lifecycle, int subId) {
mSubId = subId;
mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
.createForSubscriptionId(mSubId);
@@ -221,6 +232,29 @@
CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL)
: false;
+ mServiceStateStatus = new ServiceStateStatus(lifecycle, mTelephonyManager,
+ new HandlerExecutor(mUiHandler)) {
+ @Override
+ protected void setValue(ServiceState status) {
+ if (status == null) {
+ return;
+ }
+ updateUiAutoSelectValue(status);
+ }
+ };
+
+ ThreadUtils.postOnBackgroundThread(() -> {
+ queryNetworkSelectionMode(INTERNAL_LOG_TAG_INIT);
+
+ //Update UI in UI thread
+ mUiHandler.post(() -> {
+ if (mSwitchPreference != null) {
+ mRecursiveUpdate.getAndIncrement();
+ mSwitchPreference.setChecked(isChecked());
+ mRecursiveUpdate.decrementAndGet();
+ }
+ });
+ });
return this;
}
@@ -230,6 +264,41 @@
return this;
}
+ private void queryNetworkSelectionMode(String tag) {
+ mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode();
+ Log.d(LOG_TAG, tag + ": query commend done. mCacheOfModeStatus: " + mCacheOfModeStatus);
+ updateListenerValue();
+ }
+
+ @VisibleForTesting
+ void updateUiAutoSelectValue(ServiceState status) {
+ if (status == null) {
+ return;
+ }
+ if (!mUpdatingConfig.get()) {
+ int networkSelectionMode = status.getIsManualSelection()
+ ? TelephonyManager.NETWORK_SELECTION_MODE_MANUAL
+ : TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
+ if (mCacheOfModeStatus == networkSelectionMode) {
+ return;
+ }
+ mCacheOfModeStatus = networkSelectionMode;
+ Log.d(LOG_TAG, "updateUiAutoSelectValue: mCacheOfModeStatus: " + mCacheOfModeStatus);
+ updateListenerValue();
+
+ mRecursiveUpdate.getAndIncrement();
+ updateState(mSwitchPreference);
+ mRecursiveUpdate.decrementAndGet();
+
+ }
+ }
+
+ private void updateListenerValue() {
+ for (OnNetworkSelectModeListener lsn : mListeners) {
+ lsn.onNetworkSelectModeUpdated(mCacheOfModeStatus);
+ }
+ }
+
private void showAutoSelectProgressBar() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(mContext);
diff --git a/src/com/android/settings/notification/DockAudioMediaPreferenceController.java b/src/com/android/settings/notification/DockAudioMediaPreferenceController.java
index d9367d5..7170434 100644
--- a/src/com/android/settings/notification/DockAudioMediaPreferenceController.java
+++ b/src/com/android/settings/notification/DockAudioMediaPreferenceController.java
@@ -19,6 +19,8 @@
import static com.android.settings.notification.SettingPref.TYPE_GLOBAL;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
import android.provider.Settings.Global;
@@ -41,7 +43,7 @@
DEFAULT_DOCK_AUDIO_MEDIA, DOCK_AUDIO_MEDIA_DISABLED, DOCK_AUDIO_MEDIA_ENABLED) {
@Override
public boolean isApplicable(Context context) {
- return context.getResources().getBoolean(
+ return isLeDesk() && context.getResources().getBoolean(
com.android.settings.R.bool.has_dock_settings);
}
@@ -60,4 +62,18 @@
}
};
}
+
+ /**
+ * Checks the state of docking type
+ * @return true if it is low-end dock types
+ */
+ private boolean isLeDesk() {
+ IntentFilter intentFilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
+ Intent dockStatus = mContext.registerReceiver(null, intentFilter);
+ if (dockStatus == null) {
+ return false;
+ }
+ int dockState = dockStatus.getIntExtra(Intent.EXTRA_DOCK_STATE, -1);
+ return dockState == Intent.EXTRA_DOCK_STATE_LE_DESK;
+ }
}
diff --git a/src/com/android/settings/notification/zen/ZenModeBackend.java b/src/com/android/settings/notification/zen/ZenModeBackend.java
index 85f9aee..1079865 100644
--- a/src/com/android/settings/notification/zen/ZenModeBackend.java
+++ b/src/com/android/settings/notification/zen/ZenModeBackend.java
@@ -312,21 +312,6 @@
return R.string.zen_mode_from_no_conversations;
}
- protected int getConversationSummary() {
- int conversationType = getPriorityConversationSenders();
-
- switch (conversationType) {
- case NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE:
- return R.string.zen_mode_from_all_conversations;
- case NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT:
- return R.string.zen_mode_from_important_conversations;
- case NotificationManager.Policy.CONVERSATION_SENDERS_NONE:
- return R.string.zen_mode_from_no_conversations;
- default:
- return R.string.zen_mode_from_no_conversations;
- }
- }
-
protected int getContactsCallsSummary(ZenPolicy policy) {
int peopleType = policy.getPriorityCallSenders();
switch (peopleType) {
diff --git a/src/com/android/settings/notification/zen/ZenModeConversationsImagePreferenceController.java b/src/com/android/settings/notification/zen/ZenModeConversationsImagePreferenceController.java
deleted file mode 100644
index 78c8134..0000000
--- a/src/com/android/settings/notification/zen/ZenModeConversationsImagePreferenceController.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2020 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.notification.zen;
-
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
-
-import android.content.Context;
-import android.content.pm.ParceledListSlice;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.service.notification.ConversationChannelWrapper;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.notification.NotificationBackend;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.widget.LayoutPreference;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Updates the DND Settings conversations image resource based on the conversations channels.
- */
-public class ZenModeConversationsImagePreferenceController
- extends AbstractZenModePreferenceController {
- private static final int MAX_CONVERSATIONS_SHOWN = 5;
- private final int mIconSizePx;
- private final int mIconOffsetPx;
- private final ArrayList<Drawable> mConversationDrawables = new ArrayList<>();
- private final NotificationBackend mNotificationBackend;
-
- private ViewGroup mViewGroup;
- private LayoutPreference mPreference;
-
- public ZenModeConversationsImagePreferenceController(Context context, String key,
- Lifecycle lifecycle, NotificationBackend notificationBackend) {
- super(context, key, lifecycle);
- mNotificationBackend = notificationBackend;
- mIconSizePx =
- mContext.getResources().getDimensionPixelSize(R.dimen.zen_conversations_icon_size);
- mIconOffsetPx = mContext.getResources()
- .getDimensionPixelSize(R.dimen.zen_conversations_icon_offset);
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = (LayoutPreference) screen.findPreference(KEY);
- mViewGroup =
- (ViewGroup) mPreference.findViewById(R.id.zen_mode_settings_senders_overlay_view);
- loadConversations();
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public void updateState(Preference preference) {
- loadConversations();
-
- mViewGroup.removeAllViews();
- final int conversationSenders = mBackend.getPriorityConversationSenders();
- if (conversationSenders == CONVERSATION_SENDERS_ANYONE) {
- mViewGroup.setContentDescription(
- mContext.getResources().getString(R.string.zen_mode_from_all_conversations));
- } else if (conversationSenders == CONVERSATION_SENDERS_IMPORTANT) {
- mViewGroup.setContentDescription(
- mContext.getResources().getString(
- R.string.zen_mode_from_important_conversations));
- } else {
- mViewGroup.setContentDescription(null);
- mViewGroup.setVisibility(View.GONE);
- return;
- }
-
- final int numDrawablesToShow = Math.min(MAX_CONVERSATIONS_SHOWN,
- mConversationDrawables.size());
- for (int i = 0; i < numDrawablesToShow; i++) {
- ImageView iv = new ImageView(mContext);
- iv.setImageDrawable(mConversationDrawables.get(i));
- iv.setLayoutParams(new ViewGroup.LayoutParams(mIconSizePx, mIconSizePx));
-
- FrameLayout fl = new FrameLayout(mContext);
- fl.addView(iv);
- fl.setPadding((numDrawablesToShow - i - 1) * mIconOffsetPx, 0, 0, 0);
- mViewGroup.addView(fl);
- }
-
- mViewGroup.setVisibility(numDrawablesToShow > 0 ? View.VISIBLE : View.GONE);
- }
-
- private void loadConversations() {
- // Load conversations
- new AsyncTask<Void, Void, Void>() {
- private List<Drawable> mDrawables = new ArrayList<>();
- @Override
- protected Void doInBackground(Void... unused) {
- mDrawables.clear();
- final int conversationSenders = mBackend.getPriorityConversationSenders();
- if (conversationSenders == CONVERSATION_SENDERS_NONE) {
- return null;
- }
- ParceledListSlice<ConversationChannelWrapper> conversations =
- mNotificationBackend.getConversations(
- conversationSenders == CONVERSATION_SENDERS_IMPORTANT);
- if (conversations != null) {
- for (ConversationChannelWrapper conversation : conversations.getList()) {
- if (!conversation.getNotificationChannel().isDemoted()) {
- Drawable drawable = mNotificationBackend.getConversationDrawable(
- mContext,
- conversation.getShortcutInfo(),
- conversation.getPkg(),
- conversation.getUid(),
- conversation.getNotificationChannel()
- .isImportantConversation());
- if (drawable != null) {
- mDrawables.add(drawable);
- }
- }
- }
- }
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Void unused) {
- if (mContext == null) {
- return;
- }
- mConversationDrawables.clear();
- mConversationDrawables.addAll(mDrawables);
- updateState(mPreference);
- }
- }.execute();
- }
-}
diff --git a/src/com/android/settings/notification/zen/ZenModeConversationsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeConversationsPreferenceController.java
deleted file mode 100644
index f23bf61..0000000
--- a/src/com/android/settings/notification/zen/ZenModeConversationsPreferenceController.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 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.notification.zen;
-
-import android.app.NotificationManager;
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-/**
- * Controls the summary for preference found at:
- * Settings > Sound > Do Not Disturb > People > Conversations
- */
-public class ZenModeConversationsPreferenceController extends AbstractZenModePreferenceController {
- private final ZenModeBackend mBackend;
- private Preference mPreference;
-
- public ZenModeConversationsPreferenceController(Context context,
- String key, Lifecycle lifecycle) {
- super(context, key, lifecycle);
- mBackend = ZenModeBackend.getInstance(context);
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = screen.findPreference(KEY);
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
- switch (getZenMode()) {
- case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
- case Settings.Global.ZEN_MODE_ALARMS:
- mPreference.setEnabled(false);
- mPreference.setSummary(mBackend.getAlarmsTotalSilencePeopleSummary(
- NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS));
- break;
- default:
- preference.setEnabled(true);
- preference.setSummary(mBackend.getConversationSummary());
- }
- }
-}
diff --git a/src/com/android/settings/notification/zen/ZenModeConversationsSettings.java b/src/com/android/settings/notification/zen/ZenModeConversationsSettings.java
deleted file mode 100644
index 5c68126..0000000
--- a/src/com/android/settings/notification/zen/ZenModeConversationsSettings.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2020 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.notification.zen;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.notification.NotificationBackend;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.search.SearchIndexable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Settings > Sound > Do Not Disturb > Conversations
- */
-@SearchIndexable
-public class ZenModeConversationsSettings extends ZenModeSettingsBase {
- private final NotificationBackend mNotificationBackend = new NotificationBackend();
-
- @Override
- protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, getSettingsLifecycle(), mNotificationBackend);
- }
-
- private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
- Lifecycle lifecycle, NotificationBackend notificationBackend) {
- List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new ZenModeConversationsImagePreferenceController(context,
- "zen_mode_conversations_image", lifecycle, notificationBackend));
- controllers.add(new ZenModePriorityConversationsPreferenceController(context,
- "zen_mode_conversations_radio_buttons", lifecycle, notificationBackend));
- return controllers;
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.zen_mode_conversations_settings;
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DND_CONVERSATIONS;
- }
-
- /**
- * For Search.
- */
- public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.zen_mode_conversations_settings) {
-
- @Override
- public List<AbstractPreferenceController> createPreferenceControllers(
- Context context) {
- return buildPreferenceControllers(context, null, null);
- }
- };
-}
diff --git a/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceController.java
deleted file mode 100644
index a8387a3..0000000
--- a/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceController.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2020 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.notification.zen;
-
-import android.app.NotificationManager;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.pm.ParceledListSlice;
-import android.icu.text.MessageFormat;
-import android.os.AsyncTask;
-import android.service.notification.ConversationChannelWrapper;
-import android.view.View;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.notification.NotificationBackend;
-import com.android.settings.notification.app.ConversationListSettings;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Options to choose the priority conversations that are allowed to bypass DND.
- */
-public class ZenModePriorityConversationsPreferenceController
- extends AbstractZenModePreferenceController {
- private static final int UNSET = -1;
- @VisibleForTesting static final String KEY_ALL = "conversations_all";
- @VisibleForTesting static final String KEY_IMPORTANT = "conversations_important";
- @VisibleForTesting static final String KEY_NONE = "conversations_none";
-
- private final NotificationBackend mNotificationBackend;
-
- private int mNumImportantConversations = UNSET;
- private int mNumConversations = UNSET;
- private PreferenceCategory mPreferenceCategory;
- private List<SelectorWithWidgetPreference> mSelectorWithWidgetPreferences = new ArrayList<>();
- private Context mPreferenceScreenContext;
-
- public ZenModePriorityConversationsPreferenceController(Context context, String key,
- Lifecycle lifecycle, NotificationBackend notificationBackend) {
- super(context, key, lifecycle);
- mNotificationBackend = notificationBackend;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- mPreferenceScreenContext = screen.getContext();
- mPreferenceCategory = screen.findPreference(getPreferenceKey());
- if (mPreferenceCategory.findPreference(KEY_ALL) == null) {
- makeRadioPreference(KEY_ALL, R.string.zen_mode_from_all_conversations);
- makeRadioPreference(KEY_IMPORTANT, R.string.zen_mode_from_important_conversations);
- makeRadioPreference(KEY_NONE, R.string.zen_mode_from_no_conversations);
- updateChannelCounts();
- }
-
- super.displayPreference(screen);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- updateChannelCounts();
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public void updateState(Preference preference) {
- final int currSetting = mBackend.getPriorityConversationSenders();
-
- for (SelectorWithWidgetPreference pref : mSelectorWithWidgetPreferences) {
- pref.setChecked(keyToSetting(pref.getKey()) == currSetting);
- pref.setSummary(getSummary(pref.getKey()));
- }
- }
-
- private static int keyToSetting(String key) {
- switch (key) {
- case KEY_ALL:
- return NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
- case KEY_IMPORTANT:
- return NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
- default:
- return NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
- }
- }
-
- private String getSummary(String key) {
- int numConversations;
- if (KEY_ALL.equals(key)) {
- numConversations = mNumConversations;
- } else if (KEY_IMPORTANT.equals(key)) {
- numConversations = mNumImportantConversations;
- } else {
- return null;
- }
-
- if (numConversations == UNSET) {
- return null;
- } else {
- MessageFormat msgFormat = new MessageFormat(
- mContext.getString(R.string.zen_mode_conversations_count),
- Locale.getDefault());
- Map<String, Object> args = new HashMap<>();
- args.put("count", numConversations);
- return msgFormat.format(args);
- }
- }
-
- private void updateChannelCounts() {
- // Load conversations
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... unused) {
- ParceledListSlice<ConversationChannelWrapper> allConversations =
- mNotificationBackend.getConversations(false);
- int numConversations = 0;
- if (allConversations != null) {
- for (ConversationChannelWrapper conversation : allConversations.getList()) {
- if (!conversation.getNotificationChannel().isDemoted()) {
- numConversations++;
- }
- }
- }
- mNumConversations = numConversations;
-
- ParceledListSlice<ConversationChannelWrapper> impConversations =
- mNotificationBackend.getConversations(true);
- int numImportantConversations = 0;
- if (impConversations != null) {
- for (ConversationChannelWrapper conversation : impConversations.getList()) {
- if (!conversation.getNotificationChannel().isDemoted()) {
- numImportantConversations++;
- }
- }
- }
- mNumImportantConversations = numImportantConversations;
- return null;
- }
-
- @Override
- protected void onPostExecute(Void unused) {
- if (mContext == null) {
- return;
- }
- updateState(mPreferenceCategory);
- }
- }.execute();
- }
-
- private SelectorWithWidgetPreference makeRadioPreference(String key, int titleId) {
- final SelectorWithWidgetPreference pref =
- new SelectorWithWidgetPreference(mPreferenceCategory.getContext());
- if (KEY_ALL.equals(key) || KEY_IMPORTANT.equals(key)) {
- pref.setExtraWidgetOnClickListener(mConversationSettingsWidgetClickListener);
- }
- pref.setKey(key);
- pref.setTitle(titleId);
- pref.setOnClickListener(mRadioButtonClickListener);
- mPreferenceCategory.addPreference(pref);
- mSelectorWithWidgetPreferences.add(pref);
- return pref;
- }
-
- private View.OnClickListener mConversationSettingsWidgetClickListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- new SubSettingLauncher(mPreferenceScreenContext)
- .setDestination(ConversationListSettings.class.getName())
- .setSourceMetricsCategory(SettingsEnums.DND_CONVERSATIONS)
- .launch();
- }
- };
-
- private SelectorWithWidgetPreference.OnClickListener mRadioButtonClickListener =
- new SelectorWithWidgetPreference.OnClickListener() {
- @Override
- public void onRadioButtonClicked(SelectorWithWidgetPreference preference) {
- int selectedConversationSetting = keyToSetting(preference.getKey());
- if (selectedConversationSetting != mBackend.getPriorityConversationSenders()) {
- mBackend.saveConversationSenders(selectedConversationSetting);
- }
- }
- };
-}
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index 77949eb..60b8f88 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -29,12 +29,15 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsControllerCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
/**
@@ -144,9 +147,33 @@
window.setGravity(Gravity.BOTTOM);
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT);
+ setupNavigationBar();
mPanelFragment = new PanelFragment();
mPanelFragment.setArguments(new Bundle(mBundle));
fragmentManager.beginTransaction().add(R.id.main_content, mPanelFragment).commit();
}
}
+
+ /**
+ * Adjust bottom edge and color.
+ */
+ private void setupNavigationBar() {
+ // Extend the panel all the way to the bottom of the screen, as opposed to sitting on top of
+ // the navigation bar.
+ ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView(),
+ (v, windowInsets) -> {
+ v.setPadding(v.getPaddingLeft(), v.getPaddingTop(), v.getPaddingRight(), 0);
+ return windowInsets; // propagate down to panel layout root element
+ });
+
+ // When using 3-button navigation in light mode, the system picks white navigation buttons
+ // which are not sufficiently contrasted from the panel background.
+ WindowInsetsControllerCompat windowInsetsController =
+ ViewCompat.getWindowInsetsController(getWindow().getDecorView());
+
+ if (windowInsetsController != null) {
+ boolean forceNavigationButtonsDark = !Utils.isNightMode(this);
+ windowInsetsController.setAppearanceLightNavigationBars(forceNavigationButtonsDark);
+ }
+ }
}
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 020b725..26e84be 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -21,12 +21,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
+import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.RemoteLockscreenValidationSession;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentSender;
+import android.os.Bundle;
import android.os.UserManager;
import android.util.Log;
@@ -147,7 +149,8 @@
private boolean mRemoteLockscreenValidation;
@Nullable private RemoteLockscreenValidationSession mRemoteLockscreenValidationSession;
@Nullable private ComponentName mRemoteLockscreenValidationServiceComponent;
- boolean mRequestGatekeeperPasswordHandle;
+ private boolean mRequestGatekeeperPasswordHandle;
+ private boolean mTaskOverlay;
public Builder(@NonNull Activity activity) {
mActivity = activity;
@@ -253,6 +256,14 @@
}
/**
+ * @param taskOverlay specifies whether the activity should be launched as a task overlay.
+ */
+ @NonNull public Builder setTaskOverlay(boolean taskOverlay) {
+ mTaskOverlay = taskOverlay;
+ return this;
+ }
+
+ /**
* @param foregroundOnly if true, the confirmation activity will be finished if it loses
* foreground.
*/
@@ -371,7 +382,8 @@
mBuilder.mCheckBoxLabel, mBuilder.mRemoteLockscreenValidation,
mBuilder.mRemoteLockscreenValidationSession,
mBuilder.mRemoteLockscreenValidationServiceComponent, mBuilder.mAllowAnyUserId,
- mBuilder.mForegroundOnly, mBuilder.mRequestGatekeeperPasswordHandle);
+ mBuilder.mForegroundOnly, mBuilder.mRequestGatekeeperPasswordHandle,
+ mBuilder.mTaskOverlay);
}
private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@@ -381,7 +393,8 @@
@Nullable CharSequence checkboxLabel, boolean remoteLockscreenValidation,
@Nullable RemoteLockscreenValidationSession remoteLockscreenValidationSession,
@Nullable ComponentName remoteLockscreenValidationServiceComponent,
- boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
+ boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle,
+ boolean taskOverlay) {
Optional<Class<?>> activityClass = determineAppropriateActivityClass(
returnCredentials, forceVerifyPath, userId, remoteLockscreenValidationSession);
if (activityClass.isEmpty()) {
@@ -392,7 +405,7 @@
returnCredentials, external, forceVerifyPath, userId, alternateButton,
checkboxLabel, remoteLockscreenValidation, remoteLockscreenValidationSession,
remoteLockscreenValidationServiceComponent, allowAnyUser, foregroundOnly,
- requestGatekeeperPasswordHandle);
+ requestGatekeeperPasswordHandle, taskOverlay);
}
private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
@@ -402,7 +415,8 @@
boolean remoteLockscreenValidation,
@Nullable RemoteLockscreenValidationSession remoteLockscreenValidationSession,
@Nullable ComponentName remoteLockscreenValidationServiceComponent,
- boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
+ boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle,
+ boolean taskOverlay) {
final Intent intent = new Intent();
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
@@ -434,28 +448,39 @@
Intent inIntent = mFragment != null ? mFragment.getActivity().getIntent() :
mActivity.getIntent();
copyInternalExtras(inIntent, intent);
+ Bundle launchOptions = createLaunchOptions(taskOverlay);
if (external) {
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
copyOptionalExtras(inIntent, intent);
if (mActivityResultLauncher != null) {
mActivityResultLauncher.launch(intent);
} else if (mFragment != null) {
- mFragment.startActivity(intent);
+ mFragment.startActivity(intent, launchOptions);
} else {
- mActivity.startActivity(intent);
+ mActivity.startActivity(intent, launchOptions);
}
} else {
if (mActivityResultLauncher != null) {
mActivityResultLauncher.launch(intent);
} else if (mFragment != null) {
- mFragment.startActivityForResult(intent, request);
+ mFragment.startActivityForResult(intent, request, launchOptions);
} else {
- mActivity.startActivityForResult(intent, request);
+ mActivity.startActivityForResult(intent, request, launchOptions);
}
}
return true;
}
+ private Bundle createLaunchOptions(boolean taskOverlay) {
+ if (!taskOverlay) {
+ return null;
+ }
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchTaskId(mActivity.getTaskId());
+ options.setTaskOverlay(true /* taskOverlay */, true /* canResume */);
+ return options.toBundle();
+ }
+
private Optional<Integer> passwordQualityToLockTypes(int quality) {
switch (quality) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index 328e440..fbcebb8 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -24,8 +24,6 @@
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONFIRM_PATTERN;
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_CONFIRM_PIN;
-import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
-
import android.app.Activity;
import android.app.KeyguardManager;
import android.app.RemoteLockscreenValidationSession;
@@ -63,13 +61,6 @@
public class ConfirmDeviceCredentialActivity extends FragmentActivity {
public static final String TAG = ConfirmDeviceCredentialActivity.class.getSimpleName();
- /**
- * If the intent is sent from {@link com.android.systemui.keyguard.WorkLockActivityController}
- * then check for device policy management flags.
- */
- public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY_CONTROLLER =
- "from_work_lock_activity_controller";
-
// The normal flow that apps go through
private static final int CREDENTIAL_NORMAL = 1;
// Unlocks the managed profile when the primary profile is unlocked
@@ -80,15 +71,6 @@
public static class InternalActivity extends ConfirmDeviceCredentialActivity {
}
- public static Intent createIntent(CharSequence title, CharSequence details) {
- Intent intent = new Intent();
- intent.setClassName(SETTINGS_PACKAGE_NAME,
- ConfirmDeviceCredentialActivity.class.getName());
- intent.putExtra(KeyguardManager.EXTRA_TITLE, title);
- intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION, details);
- return intent;
- }
-
private BiometricFragment mBiometricFragment;
private DevicePolicyManager mDevicePolicyManager;
private LockPatternUtils mLockPatternUtils;
@@ -97,6 +79,7 @@
private Handler mHandler = new Handler(Looper.getMainLooper());
private Context mContext;
private boolean mCheckDevicePolicyManager;
+ private boolean mTaskOverlay;
private String mTitle;
private CharSequence mDetails;
@@ -186,6 +169,8 @@
boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
boolean remoteValidation =
KeyguardManager.ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL.equals(intent.getAction());
+ mTaskOverlay = isInternalActivity()
+ && intent.getBooleanExtra(KeyguardManager.EXTRA_FORCE_TASK_OVERLAY, false);
mUserId = UserHandle.myUserId();
if (isInternalActivity()) {
@@ -417,6 +402,12 @@
*/
private void showConfirmCredentials() {
boolean launched = false;
+ ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(this)
+ .setHeader(mTitle)
+ .setDescription(mDetails)
+ .setExternal(true)
+ .setUserId(mUserId)
+ .setTaskOverlay(mTaskOverlay);
// The only difference between CREDENTIAL_MANAGED and CREDENTIAL_NORMAL is that for
// CREDENTIAL_MANAGED, we launch the real confirm credential activity with an explicit
// but fake challenge value (0L). This will result in ConfirmLockPassword calling
@@ -429,22 +420,9 @@
// LockPatternChecker and LockPatternUtils. verifyPassword should be the only API to use,
// which optionally accepts a challenge.
if (mCredentialMode == CREDENTIAL_MANAGED) {
- final ChooseLockSettingsHelper.Builder builder =
- new ChooseLockSettingsHelper.Builder(this);
- launched = builder.setHeader(mTitle)
- .setDescription(mDetails)
- .setExternal(true)
- .setUserId(mUserId)
- .setForceVerifyPath(true)
- .show();
+ launched = builder.setForceVerifyPath(true).show();
} else if (mCredentialMode == CREDENTIAL_NORMAL) {
- final ChooseLockSettingsHelper.Builder builder =
- new ChooseLockSettingsHelper.Builder(this);
- launched = builder.setHeader(mTitle) // Show the title string in the header area
- .setDescription(mDetails)
- .setExternal(true)
- .setUserId(mUserId)
- .show();
+ launched = builder.show();
}
if (!launched) {
Log.d(TAG, "No pin/pattern/pass set");
diff --git a/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java b/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java
index 20d7f58..1c5015f 100644
--- a/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java
+++ b/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java
@@ -23,6 +23,7 @@
import androidx.annotation.VisibleForTesting;
+import com.android.internal.app.LocaleHelper;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -53,9 +54,8 @@
Log.w(getLogTag(), "No selected language.");
return "";
}
- return Locale.forLanguageTag(selectedLanguage)
- .stripExtensions()
- .getDisplayName(Locale.forLanguageTag(selectedLanguage));
+ Locale locale = Locale.forLanguageTag(selectedLanguage);
+ return LocaleHelper.getDisplayName(locale.stripExtensions(), locale, true);
}
Log.w(getLogTag(), "Incorrect option : " + option);
return "";
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragmentTest.java
index b2da579..9bd4f1b 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragmentTest.java
@@ -26,8 +26,6 @@
import androidx.test.core.app.ApplicationProvider;
-import com.android.settings.R;
-import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -44,8 +42,6 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
-import java.util.List;
-
/** Tests for {@link BluetoothDetailsAudioRoutingFragment}. */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothUtils.class})
@@ -92,17 +88,6 @@
assertThat(mFragment.mCachedDevice.getAddress()).isEqualTo(TEST_ADDRESS);
}
- @Test
- public void getNonIndexableKeys_existInXmlLayout() {
- final List<String> niks = BluetoothDetailsAudioRoutingFragment.SEARCH_INDEX_DATA_PROVIDER
- .getNonIndexableKeys(mContext);
- final List<String> keys =
- XmlTestUtils.getKeysFromPreferenceXml(mContext,
- R.xml.bluetooth_audio_routing_fragment);
-
- assertThat(keys).containsAtLeastElementsIn(niks);
- }
-
private void setupEnvironment() {
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
diff --git a/tests/robotests/src/com/android/settings/dream/DreamHomeControlsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/dream/DreamHomeControlsPreferenceControllerTest.java
new file mode 100644
index 0000000..452604c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/dream/DreamHomeControlsPreferenceControllerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 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.dream;
+
+import static com.android.settingslib.dream.DreamBackend.COMPLICATION_TYPE_HOME_CONTROLS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.util.ArraySet;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.dream.DreamBackend;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowContentResolver;
+import org.robolectric.shadows.ShadowSettings;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowSettings.ShadowSecure.class})
+public class DreamHomeControlsPreferenceControllerTest {
+
+ private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PreferenceScreen mScreen;
+ private DreamHomeControlsPreferenceController mController;
+ private SwitchPreference mPreference;
+ private DreamBackend mBackend;
+ private ShadowContentResolver mShadowContentResolver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = ApplicationProvider.getApplicationContext();
+ mShadowContentResolver = Shadow.extract(mContext.getContentResolver());
+ mBackend = new DreamBackend(mContext);
+ mController = new DreamHomeControlsPreferenceController(mContext, "key", mBackend);
+ mPreference = new SwitchPreference(mContext);
+ mPreference.setKey(mController.getPreferenceKey());
+ when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+
+ // Make home controls supported by default
+ mBackend.setSupportedComplications(
+ new ArraySet<>(new Integer[]{COMPLICATION_TYPE_HOME_CONTROLS}));
+ }
+
+ @After
+ public void tearDown() {
+ ShadowSettings.ShadowSecure.reset();
+ }
+
+ @Test
+ public void testSetChecked_setTrue_enablesSetting() {
+ mBackend.setHomeControlsEnabled(false);
+ assertThat(mBackend.getEnabledComplications())
+ .doesNotContain(COMPLICATION_TYPE_HOME_CONTROLS);
+
+ mController.setChecked(true);
+ assertThat(mBackend.getEnabledComplications())
+ .contains(COMPLICATION_TYPE_HOME_CONTROLS);
+ }
+
+ @Test
+ public void testSetChecked_setFalse_disablesSetting() {
+ mBackend.setHomeControlsEnabled(true);
+ assertThat(mBackend.getEnabledComplications())
+ .contains(COMPLICATION_TYPE_HOME_CONTROLS);
+
+ mController.setChecked(false);
+ assertThat(mBackend.getEnabledComplications())
+ .doesNotContain(COMPLICATION_TYPE_HOME_CONTROLS);
+ }
+
+ @Test
+ public void testIsChecked_returnsFalse() {
+ mBackend.setHomeControlsEnabled(false);
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testIsChecked_returnsTrue() {
+ mBackend.setHomeControlsEnabled(true);
+ assertThat(mBackend.getEnabledComplications())
+ .contains(COMPLICATION_TYPE_HOME_CONTROLS);
+ assertThat(mController.isChecked()).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/DockAudioMediaPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/DockAudioMediaPreferenceControllerTest.java
index d237b27..5e4efd0 100644
--- a/tests/robotests/src/com/android/settings/notification/DockAudioMediaPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/DockAudioMediaPreferenceControllerTest.java
@@ -19,14 +19,19 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.provider.Settings.Global;
import androidx.fragment.app.FragmentActivity;
@@ -72,6 +77,7 @@
mController = new DockAudioMediaPreferenceController(mContext, mSetting, null);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
doReturn(mScreen).when(mSetting).getPreferenceScreen();
+ fakeDockState(Intent.EXTRA_DOCK_STATE_LE_DESK);
}
@Test
@@ -91,6 +97,34 @@
}
@Test
+ public void isAvailable_undocked_shouldReturnFalse() {
+ when(mContext.registerReceiver(nullable(BroadcastReceiver.class),
+ any(IntentFilter.class))).thenReturn(null);
+ when(mContext.getResources().getBoolean(com.android.settings.R.bool.has_dock_settings))
+ .thenReturn(true);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_highEndDock_shouldReturnFalse() {
+ fakeDockState(Intent.EXTRA_DOCK_STATE_HE_DESK);
+ when(mContext.getResources().getBoolean(com.android.settings.R.bool.has_dock_settings))
+ .thenReturn(true);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_lowEndDock_shouldReturnTrue() {
+ fakeDockState(Intent.EXTRA_DOCK_STATE_LE_DESK);
+ when(mContext.getResources().getBoolean(com.android.settings.R.bool.has_dock_settings))
+ .thenReturn(true);
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
public void displayPreference_dockAudioDisabled_shouldSelectFirstItem() {
Global.putInt(mContentResolver, Global.DOCK_AUDIO_MEDIA_ENABLED, 0);
@@ -127,4 +161,11 @@
assertThat(Global.getInt(mContentResolver, Global.DOCK_AUDIO_MEDIA_ENABLED, 0))
.isEqualTo(1);
}
+
+ private void fakeDockState(int dockState) {
+ Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
+ intent.putExtra(Intent.EXTRA_DOCK_STATE, dockState);
+ when(mContext.registerReceiver(nullable(BroadcastReceiver.class),
+ any(IntentFilter.class))).thenReturn(intent);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceControllerTest.java
deleted file mode 100644
index d5834f9..0000000
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceControllerTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2020 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.notification.zen;
-
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
-
-import static com.android.settings.notification.zen.ZenModePriorityConversationsPreferenceController.KEY_ALL;
-import static com.android.settings.notification.zen.ZenModePriorityConversationsPreferenceController.KEY_IMPORTANT;
-import static com.android.settings.notification.zen.ZenModePriorityConversationsPreferenceController.KEY_NONE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationManager;
-import android.content.ContentResolver;
-import android.content.Context;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.notification.NotificationBackend;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class ZenModePriorityConversationsPreferenceControllerTest {
-
- private ZenModePriorityConversationsPreferenceController mController;
-
- @Mock
- private ZenModeBackend mZenBackend;
- @Mock
- private PreferenceCategory mMockPrefCategory;
- @Mock
- private NotificationManager.Policy mPolicy;
- @Mock
- private PreferenceScreen mPreferenceScreen;
- @Mock
- private NotificationBackend mNotifBackend;
-
- private List<SelectorWithWidgetPreference> mSelectorWithWidgetPreferences;
- private ContentResolver mContentResolver;
- private Context mContext;
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- mController = new ZenModePriorityConversationsPreferenceController(
- mContext, "test_key", mock(Lifecycle.class), mNotifBackend);
- ReflectionHelpers.setField(mController, "mBackend", mZenBackend);
-
- when(mMockPrefCategory.getContext()).thenReturn(mContext);
- when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
- .thenReturn(mMockPrefCategory);
- captureRadioButtons();
- }
-
- @Test
- public void displayPreference_radioButtonsCreatedOnlyOnce() {
- when(mMockPrefCategory.findPreference(any())).thenReturn(mock(Preference.class));
-
- // radio buttons were already created, so don't re-create them
- mController.displayPreference(mPreferenceScreen);
- verify(mMockPrefCategory, never()).addPreference(any());
- }
-
- @Test
- public void clickAllConversations() {
- SelectorWithWidgetPreference allConversationsRb = getButton(KEY_ALL);
- allConversationsRb.onClick();
-
- verify(mZenBackend).saveConversationSenders(CONVERSATION_SENDERS_ANYONE);
- }
-
- @Test
- public void clickImportantConversations() {
- SelectorWithWidgetPreference importantConversationsRb = getButton(KEY_IMPORTANT);
- importantConversationsRb.onClick();
-
- verify(mZenBackend).saveConversationSenders(CONVERSATION_SENDERS_IMPORTANT);
- }
-
- @Test
- public void clickNoConversations() {
- SelectorWithWidgetPreference noConversationsRb = getButton(KEY_NONE);
- noConversationsRb.onClick();
-
- verify(mZenBackend)
- .saveConversationSenders(CONVERSATION_SENDERS_NONE);
- }
-
- private void captureRadioButtons() {
- ArgumentCaptor<SelectorWithWidgetPreference> rbCaptor =
- ArgumentCaptor.forClass(SelectorWithWidgetPreference.class);
- mController.displayPreference(mPreferenceScreen);
-
- // verifies 3 buttons were added
- verify(mMockPrefCategory, times(3)).addPreference(rbCaptor.capture());
- mSelectorWithWidgetPreferences = rbCaptor.getAllValues();
- assertThat(mSelectorWithWidgetPreferences.size()).isEqualTo(3);
-
- reset(mMockPrefCategory);
- }
-
- private SelectorWithWidgetPreference getButton(String key) {
- for (SelectorWithWidgetPreference pref : mSelectorWithWidgetPreferences) {
- if (key.equals(pref.getKey())) {
- return pref;
- }
- }
- return null;
- }
-}
diff --git a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
index 5cdc12a..ea55b90 100644
--- a/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
+++ b/tests/robotests/src/com/android/settings/panel/SettingsPanelActivityTest.java
@@ -16,11 +16,13 @@
package com.android.settings.panel;
+import static android.content.res.Configuration.UI_MODE_NIGHT_NO;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -30,15 +32,20 @@
import android.content.res.Configuration;
import android.os.Build;
+import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsControllerCompat;
import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -61,6 +68,9 @@
private PanelFragment mPanelFragment;
@Mock
private FragmentManager mFragmentManager;
+ @Mock
+ private FragmentTransaction mTransaction;
+ private int mOriginalUiMode;
@Before
public void setUp() {
@@ -76,6 +86,15 @@
mSettingsPanelActivity.mPanelFragment = mPanelFragment;
when(mFragmentManager.findFragmentById(R.id.main_content)).thenReturn(mPanelFragment);
when(mSettingsPanelActivity.getSupportFragmentManager()).thenReturn(mFragmentManager);
+ mOriginalUiMode = mSettingsPanelActivity.getResources().getConfiguration().uiMode;
+ when(mFragmentManager.beginTransaction()).thenReturn(mTransaction);
+ when(mTransaction.add(anyInt(), any())).thenReturn(mTransaction);
+ when(mTransaction.commit()).thenReturn(0); // don't care about return value
+ }
+
+ @After
+ public void tearDown() {
+ mSettingsPanelActivity.getResources().getConfiguration().uiMode = mOriginalUiMode;
}
@Test
@@ -179,4 +198,24 @@
verify(mPanelFragment, never()).updatePanelWithAnimation();
}
+
+ @Test
+ public void onCreated_isWindowBottomPaddingZero() {
+ int paddingBottom = mSettingsPanelActivity.getWindow().getDecorView().getPaddingBottom();
+ assertThat(paddingBottom).isEqualTo(0);
+ }
+
+ @Test
+ public void notInNightMode_lightNavigationBarAppearance() {
+ Configuration config = mSettingsPanelActivity.getResources().getConfiguration();
+ config.uiMode = UI_MODE_NIGHT_NO;
+ mSettingsPanelActivity.onConfigurationChanged(config); // forces creation
+
+ mSettingsPanelActivity.onNewIntent(mSettingsPanelActivity.getIntent());
+ verify(mFragmentManager).beginTransaction();
+
+ View decorView = mSettingsPanelActivity.getWindow().getDecorView();
+ WindowInsetsControllerCompat controller = ViewCompat.getWindowInsetsController(decorView);
+ assertThat(controller.isAppearanceLightNavigationBars()).isTrue();
+ }
}
diff --git a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
index 2633ea7..5f7f45b 100644
--- a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
@@ -46,6 +46,7 @@
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
@RunWith(AndroidJUnit4.class)
@@ -55,6 +56,13 @@
private PreferenceScreen mScreen;
private PreferenceCategory mCredentialsPreferenceCategory;
+ private static final String TEST_PACKAGE_NAME_A = "com.android.providerA";
+ private static final String TEST_PACKAGE_NAME_B = "com.android.providerB";
+ private static final String TEST_PACKAGE_NAME_C = "com.android.providerC";
+ private static final String TEST_TITLE_APP_A = "test app A";
+ private static final String TEST_TITLE_APP_B = "test app B";
+ private static final String TEST_TITLE_SERVICE_C = "test service C1";
+
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
@@ -114,10 +122,10 @@
@Test
public void buildSwitchPreference() {
CredentialProviderInfo providerInfo1 =
- createCredentialProviderInfo(
+ createCredentialProviderInfoWithIsEnabled(
"com.android.provider1", "ClassA", "Service Title", false);
CredentialProviderInfo providerInfo2 =
- createCredentialProviderInfo(
+ createCredentialProviderInfoWithIsEnabled(
"com.android.provider2", "ClassA", "Service Title", false);
CredentialManagerPreferenceController controller =
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
@@ -217,10 +225,10 @@
@Test
public void handlesCredentialProviderInfoEnabledDisabled() {
CredentialProviderInfo providerInfo1 =
- createCredentialProviderInfo(
+ createCredentialProviderInfoWithIsEnabled(
"com.android.provider1", "ClassA", "Service Title", false);
CredentialProviderInfo providerInfo2 =
- createCredentialProviderInfo(
+ createCredentialProviderInfoWithIsEnabled(
"com.android.provider2", "ClassA", "Service Title", true);
CredentialManagerPreferenceController controller =
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
@@ -244,6 +252,63 @@
assertThat(enabledServices.contains("com.android.provider2/ClassA")).isTrue();
}
+ @Test
+ public void displayPreference_withServices_preferencesAdded_sameAppShouldBeMerged() {
+ CredentialProviderInfo serviceA1 =
+ createCredentialProviderInfoWithAppLabel(
+ TEST_PACKAGE_NAME_A,
+ "CredManProviderA1",
+ TEST_TITLE_APP_A,
+ "test service A1");
+ CredentialProviderInfo serviceB1 =
+ createCredentialProviderInfoWithAppLabel(
+ TEST_PACKAGE_NAME_B,
+ "CredManProviderB1",
+ TEST_TITLE_APP_B,
+ "test service B");
+ CredentialProviderInfo serviceC1 =
+ createCredentialProviderInfoWithAppLabel(
+ TEST_PACKAGE_NAME_C,
+ "CredManProviderC1",
+ "test app C1",
+ TEST_TITLE_SERVICE_C);
+ CredentialProviderInfo serviceC2 =
+ createCredentialProviderInfoWithAppLabel(
+ TEST_PACKAGE_NAME_C,
+ "CredManProviderC2",
+ "test app C2",
+ TEST_TITLE_SERVICE_C);
+ CredentialProviderInfo serviceC3 =
+ createCredentialProviderInfoBuilder(
+ TEST_PACKAGE_NAME_C,
+ "CredManProviderC3",
+ "test app C3",
+ TEST_TITLE_SERVICE_C)
+ .setEnabled(true)
+ .build();
+
+ CredentialManagerPreferenceController controller =
+ createControllerWithServices(
+ Lists.newArrayList(serviceA1, serviceB1, serviceC1, serviceC2, serviceC3));
+ controller.displayPreference(mScreen);
+
+ assertThat(controller.isConnected()).isFalse();
+ assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(3);
+
+ Map<String, SwitchPreference> prefs =
+ controller.buildPreferenceList(mContext, mCredentialsPreferenceCategory);
+ assertThat(prefs.size()).isEqualTo(3);
+ assertThat(prefs.containsKey(TEST_PACKAGE_NAME_A));
+ assertThat(prefs.get(TEST_PACKAGE_NAME_A).getTitle()).isEqualTo(TEST_TITLE_APP_A);
+ assertThat(prefs.get(TEST_PACKAGE_NAME_A).isChecked()).isFalse();
+ assertThat(prefs.containsKey(TEST_PACKAGE_NAME_B));
+ assertThat(prefs.get(TEST_PACKAGE_NAME_B).getTitle()).isEqualTo(TEST_TITLE_APP_B);
+ assertThat(prefs.get(TEST_PACKAGE_NAME_B).isChecked()).isFalse();
+ assertThat(prefs.containsKey(TEST_PACKAGE_NAME_C));
+ assertThat(prefs.get(TEST_PACKAGE_NAME_C).getTitle()).isEqualTo(TEST_TITLE_SERVICE_C);
+ assertThat(prefs.get(TEST_PACKAGE_NAME_C).isChecked()).isTrue();
+ }
+
private CredentialManagerPreferenceController createControllerWithServices(
List<CredentialProviderInfo> availableServices) {
CredentialManagerPreferenceController controller =
@@ -259,23 +324,34 @@
private CredentialProviderInfo createCredentialProviderInfo(
String packageName, String className) {
- return createCredentialProviderInfo(packageName, className, null, false);
+ return createCredentialProviderInfoBuilder(packageName, className, null, "App Name")
+ .build();
}
- private CredentialProviderInfo createCredentialProviderInfo(
- String packageName, String className, CharSequence label, boolean isEnabled) {
+ private CredentialProviderInfo createCredentialProviderInfoWithIsEnabled(
+ String packageName, String className, CharSequence serviceLabel, boolean isEnabled) {
+ return createCredentialProviderInfoBuilder(packageName, className, serviceLabel, "App Name")
+ .setEnabled(isEnabled)
+ .build();
+ }
+
+ private CredentialProviderInfo createCredentialProviderInfoWithAppLabel(
+ String packageName, String className, CharSequence serviceLabel, String appLabel) {
+ return createCredentialProviderInfoBuilder(packageName, className, serviceLabel, appLabel)
+ .build();
+ }
+
+ private CredentialProviderInfo.Builder createCredentialProviderInfoBuilder(
+ String packageName, String className, CharSequence serviceLabel, String appLabel) {
ServiceInfo si = new ServiceInfo();
si.packageName = packageName;
si.name = className;
- si.nonLocalizedLabel = "test";
+ si.nonLocalizedLabel = serviceLabel;
si.applicationInfo = new ApplicationInfo();
si.applicationInfo.packageName = packageName;
- si.applicationInfo.nonLocalizedLabel = "test";
+ si.applicationInfo.nonLocalizedLabel = appLabel;
- return new CredentialProviderInfo.Builder(si)
- .setOverrideLabel(label)
- .setEnabled(isEnabled)
- .build();
+ return new CredentialProviderInfo.Builder(si).setOverrideLabel(serviceLabel);
}
}
diff --git a/tests/unit/src/com/android/settings/language/LanguagePreferenceControllerTest.java b/tests/unit/src/com/android/settings/language/LanguagePreferenceControllerTest.java
new file mode 100644
index 0000000..6622753
--- /dev/null
+++ b/tests/unit/src/com/android/settings/language/LanguagePreferenceControllerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 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.language;
+
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.util.FeatureFlagUtils;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.Settings;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class LanguagePreferenceControllerTest {
+ private boolean mCacheFeatureFlagSwitch = false;
+ private Context mContext;
+ private LanguagePreferenceController mController;
+
+ @Before
+ public void setup() {
+ mContext = ApplicationProvider.getApplicationContext();
+ mCacheFeatureFlagSwitch =
+ FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
+ mController = new LanguagePreferenceController(mContext, "key");
+
+ }
+
+ @After
+ public void tearDown() {
+ FeatureFlagUtils.setEnabled(
+ mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI, mCacheFeatureFlagSwitch);
+ }
+
+ @Test
+ public void getAvailabilityStatus_featureFlagOff_returnUnavailable() {
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI,
+ false);
+
+ int result = mController.getAvailabilityStatus();
+
+ assertEquals(CONDITIONALLY_UNAVAILABLE, result);
+ }
+
+ @Test
+ public void getAvailabilityStatus_featureFlagOff_LanguageAndInputSettingsActivityEnabled() {
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI,
+ false);
+
+ mController.getAvailabilityStatus();
+
+ assertTrue(isActivityEnable(mContext, Settings.LanguageAndInputSettingsActivity.class));
+ assertFalse(isActivityEnable(mContext, Settings.LanguageSettingsActivity.class));
+ }
+
+ @Test
+ public void getAvailabilityStatus_featureFlagOff_LanguageAndInputSettingsActivitydisabled() {
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI,
+ true);
+
+ mController.getAvailabilityStatus();
+
+ assertFalse(isActivityEnable(mContext, Settings.LanguageAndInputSettingsActivity.class));
+ assertTrue(isActivityEnable(mContext, Settings.LanguageSettingsActivity.class));
+ }
+
+ private static boolean isActivityEnable(Context context, Class klazz) {
+ PackageManager packageManager = context.getPackageManager();
+ ComponentName componentName =
+ new ComponentName(context, klazz);
+ int flag = packageManager.getComponentEnabledSetting(componentName);
+ return flag == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java
index 292b4a9..39f2050 100644
--- a/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java
@@ -28,9 +28,11 @@
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
+import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import androidx.lifecycle.Lifecycle;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -61,6 +63,10 @@
private CarrierConfigCache mCarrierConfigCache;
@Mock
private ProgressDialog mProgressDialog;
+ @Mock
+ private ServiceState mTestServiceState;
+ @Mock
+ private Lifecycle mLifecycle;
private PersistableBundle mCarrierConfig;
private AutoSelectPreferenceController mController;
@@ -88,7 +94,16 @@
mController = new AutoSelectPreferenceController(mContext, "auto_select");
mController.mProgressDialog = mProgressDialog;
mController.mSwitchPreference = mSwitchPreference;
- mController.init(SUB_ID);
+ mController.init(mLifecycle, SUB_ID);
+ sleepAfterInit();
+ }
+
+ private void sleepAfterInit() {
+ try {
+ Thread.sleep(2000);
+ } catch (Exception e) {
+ fail("Sleep timeout " + e);
+ }
}
@Test
@@ -111,7 +126,8 @@
@Test
public void updateState_isRoaming_enabled() {
- when(mTelephonyManager.getServiceState().getRoaming()).thenReturn(true);
+ when(mTelephonyManager.getServiceState()).thenReturn(mTestServiceState);
+ when(mTestServiceState.getRoaming()).thenReturn(true);
mController.updateState(mSwitchPreference);
@@ -120,7 +136,8 @@
@Test
public void updateState_notRoamingWithAutoSelectOn_disabled() {
- when(mTelephonyManager.getServiceState().getRoaming()).thenReturn(false);
+ when(mTelephonyManager.getServiceState()).thenReturn(mTestServiceState);
+ when(mTestServiceState.getRoaming()).thenReturn(false);
doReturn(OPERATOR_NAME).when(mTelephonyManager).getSimOperatorName();
mController.updateState(mSwitchPreference);
@@ -136,6 +153,34 @@
when(mCarrierConfigCache.getConfigForSubId(SUB_ID)).thenReturn(null);
// Should not crash
- mController.init(SUB_ID);
+ mController.init(mLifecycle, SUB_ID);
+ }
+
+ @Test
+ public void updateUiAutoSelectValue_serviceStateGetIsManualSelection_isCheckedFalse() {
+ when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
+ TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
+ when(mTestServiceState.getIsManualSelection()).thenReturn(true);
+ mController.init(mLifecycle, SUB_ID);
+ sleepAfterInit();
+
+ mController.updateUiAutoSelectValue(mTestServiceState);
+
+ assertThat(mController.isChecked()).isFalse();
+ assertThat(mSwitchPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void updateUiAutoSelectValue_serviceStateGetIsAutoSelection_isCheckedTrue() {
+ when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
+ TelephonyManager.NETWORK_SELECTION_MODE_MANUAL);
+ when(mTestServiceState.getIsManualSelection()).thenReturn(false);
+ mController.init(mLifecycle, SUB_ID);
+ sleepAfterInit();
+
+ mController.updateUiAutoSelectValue(mTestServiceState);
+
+ assertThat(mController.isChecked()).isTrue();
+ assertThat(mSwitchPreference.isChecked()).isTrue();
}
}