Snap for 7394644 from 49f904c649 to sc-release

Change-Id: I1ef8ed8654eece10b45fc30bec35936e5533e8cf
This commit is contained in:
android-build-team Robot
2021-05-25 01:09:21 +00:00
33 changed files with 258 additions and 826 deletions

View File

@@ -13,45 +13,54 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
android:layout_width="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:padding="@dimen/admin_details_dialog_padding" android:layout_height="wrap_content"
android:orientation="vertical"> android:paddingTop="@dimen/admin_details_dialog_padding"
android:paddingStart="@dimen/admin_details_dialog_padding"
android:paddingEnd="@dimen/admin_details_dialog_padding"
android:paddingBottom="@dimen/admin_details_dialog_padding_bottom"
android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingBottom="@dimen/admin_details_dialog_title_bottom_padding">
<ImageView
android:id="@+id/admin_support_icon"
android:layout_width="@dimen/admin_details_dialog_icon_size"
android:layout_height="@dimen/admin_details_dialog_icon_size"
android:scaleType="fitCenter"
android:contentDescription="@null"/>
<TextView
android:id="@+id/admin_support_dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:layout_marginTop="16dp"
android:gravity="center_vertical" android:gravity="center_horizontal"
android:paddingBottom="@dimen/admin_details_dialog_title_bottom_padding"> android:text="@string/disabled_by_policy_title"
<ImageView android:id="@+id/admin_support_icon" android:textAppearance="@style/TextAppearance.AdminDialogTitle"/>
android:layout_width="@dimen/admin_details_dialog_icon_size"
android:layout_height="@dimen/admin_details_dialog_icon_size"
android:scaleType="fitCenter"
android:contentDescription="@null" />
<TextView android:id="@+id/admin_support_dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="@dimen/admin_details_dialog_padding"
android:text="@string/disabled_by_policy_title"
android:textAppearance="@style/TextAppearance.HeadLineFontFamily"/>
</LinearLayout> </LinearLayout>
<ScrollView <ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="false">
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fadeScrollbars="false"> android:orientation="vertical">
<LinearLayout <TextView
android:id="@+id/admin_support_msg"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:textAppearance="@style/TextAppearance.AdminDialogMessage"
<TextView android:id="@+id/admin_support_msg" android:maxLength="200"
android:layout_width="match_parent" android:gravity="center_horizontal"
android:layout_height="wrap_content" android:autoLink="email|phone|web"
android:textAppearance="@style/TextAppearance.HeadLineFontFamily.Subhead" android:textColor="?android:attr/textColorSecondary"/>
android:maxLength="200"
android:autoLink="email|phone|web"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@@ -133,26 +133,6 @@
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_4" /> android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_4" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="12dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_link_24dp"/>
<Space
android:layout_width="24dp"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<!-- Keep in mind --> <!-- Keep in mind -->

View File

@@ -262,8 +262,9 @@
<!-- Admin support contact details dialog. --> <!-- Admin support contact details dialog. -->
<dimen name="admin_details_dialog_padding">24dp</dimen> <dimen name="admin_details_dialog_padding">24dp</dimen>
<dimen name="admin_details_dialog_title_bottom_padding">20dp</dimen> <dimen name="admin_details_dialog_padding_bottom">32dp</dimen>
<dimen name="admin_details_dialog_icon_size">48dp</dimen> <dimen name="admin_details_dialog_title_bottom_padding">16dp</dimen>
<dimen name="admin_details_dialog_icon_size">32dp</dimen>
<dimen name="admin_details_dialog_link_padding_top">36dp</dimen> <dimen name="admin_details_dialog_link_padding_top">36dp</dimen>
<dimen name="admin_details_dialog_learn_more_button_top_margin">24dp</dimen> <dimen name="admin_details_dialog_learn_more_button_top_margin">24dp</dimen>
<dimen name="admin_details_dialog_learn_more_button_padding">8dp</dimen> <dimen name="admin_details_dialog_learn_more_button_padding">8dp</dimen>

View File

@@ -685,24 +685,24 @@
<!-- Location settings, loading the number of apps which have location permission [CHAR LIMIT=30] --> <!-- Location settings, loading the number of apps which have location permission [CHAR LIMIT=30] -->
<string name="location_settings_loading_app_permission_stats">Loading\u2026</string> <string name="location_settings_loading_app_permission_stats">Loading\u2026</string>
<!-- Location settings footer warning text when location is on [CHAR LIMIT=NONE] --> <!-- Location settings footer warning text when location is on [CHAR LIMIT=NONE] -->
<string name="location_settings_footer_location_on"> <string name="location_settings_footer_general">
&lt;br>&lt;br>Apps with the Nearby devices permission can determine the Apps with the Nearby devices permission can determine the
relative position of connected devices. relative position of connected devices.
&lt;br>&lt;br>&lt;a href="<xliff:g example="http://www.google.com" id="url">
https://support.google.com/android/answer/3467281</xliff:g>">Learn more&lt;/a>
</string> </string>
<!-- Location settings footer warning text when location is off [CHAR LIMIT=NONE] --> <!-- Location settings footer warning text when location is off [CHAR LIMIT=NONE] -->
<string name="location_settings_footer_location_off"> <string name="location_settings_footer_location_off">
Location access is off for apps and services. Your device location may still be sent to Location access is off for apps and services. Your device location may still be sent to
emergency responders when you call or text an emergency number. emergency responders when you call or text an emergency number.
</string>
&lt;br>&lt;br>Apps with the Nearby devices permission can determine the relative <!-- Location settings footer link to support page [CHAR LIMIT=NONE] -->
position of connected devices. <string name="location_settings_footer_learn_more">
&lt;a href="<xliff:g example="http://www.google.com"
&lt;br>&lt;br>&lt;a href="<xliff:g example="http://www.google.com"
id="url"> https://support.google.com/android/answer/3467281</xliff:g>">Learn more&lt;/a> id="url"> https://support.google.com/android/answer/3467281</xliff:g>">Learn more&lt;/a>
</string> </string>
<!-- Location settings footer link content description [CHAR LIMIT=NONE] -->
<string name="location_settings_footer_learn_more_content_description">
Learn more about Location Settings.
</string>
<!-- Main Settings screen setting option title for the item to take you to the accounts screen [CHAR LIMIT=22] --> <!-- Main Settings screen setting option title for the item to take you to the accounts screen [CHAR LIMIT=22] -->
<string name="account_settings_title">Accounts</string> <string name="account_settings_title">Accounts</string>

View File

@@ -871,4 +871,15 @@
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorSecondary</item> <item name="android:textColor">?android:attr/textColorSecondary</item>
</style> </style>
<style name="TextAppearance.AdminDialogTitle"
parent="@*android:style/TextAppearance.DeviceDefault.Title">
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:textSize">24sp</item>
</style>
<style name="TextAppearance.AdminDialogMessage"
parent="@*android:style/TextAppearance.DeviceDefault">
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
</resources> </resources>

View File

@@ -48,7 +48,7 @@
<item name="android:layout">@layout/preference_widget_seekbar_settings</item> <item name="android:layout">@layout/preference_widget_seekbar_settings</item>
</style> </style>
<style name="SyncSwitchPreference" parent="@style/Preference.Material"> <style name="SyncSwitchPreference" parent="@style/SettingsSwitchPreference.SettingsLib">
<item name="android:widgetLayout">@layout/preference_widget_sync_toggle</item> <item name="android:widgetLayout">@layout/preference_widget_sync_toggle</item>
</style> </style>

View File

@@ -57,7 +57,7 @@
android:key="accessibility_button_opacity" android:key="accessibility_button_opacity"
android:title="@string/accessibility_button_opacity_title" android:title="@string/accessibility_button_opacity_title"
android:persistent="false" android:persistent="false"
settings:controller="com.android.settings.accessibility.FloatingMenuOpacityPreferenceController"/> settings:controller="com.android.settings.accessibility.FloatingMenuTransparencyPreferenceController"/>
<com.android.settings.accessibility.AccessibilityFooterPreference <com.android.settings.accessibility.AccessibilityFooterPreference
android:key="accessibility_button_footer" android:key="accessibility_button_footer"

View File

@@ -29,7 +29,7 @@
<PreferenceCategory <PreferenceCategory
android:key="important_conversations" android:key="important_conversations"
android:title="@string/important_conversations" android:title="@string/important_conversations"
android:visibility="gone" settings:isPreferenceVisible="false"
settings:allowDividerAbove="false" settings:allowDividerAbove="false"
settings:allowDividerBelow="true" > settings:allowDividerBelow="true" >
<Preference <Preference
@@ -48,6 +48,7 @@
<PreferenceCategory <PreferenceCategory
android:title="@string/other_conversations" android:title="@string/other_conversations"
android:key="other_conversations" android:key="other_conversations"
settings:isPreferenceVisible="false"
settings:allowDividerAbove="true" settings:allowDividerAbove="true"
settings:allowDividerBelow="false" /> settings:allowDividerBelow="false" />
@@ -55,6 +56,7 @@
<PreferenceCategory <PreferenceCategory
android:title="@string/recent_conversations" android:title="@string/recent_conversations"
android:key="recent_conversations" android:key="recent_conversations"
settings:isPreferenceVisible="false"
settings:allowDividerAbove="true" settings:allowDividerAbove="true"
settings:allowDividerBelow="false" /> settings:allowDividerBelow="false" />

View File

@@ -70,8 +70,9 @@
</PreferenceCategory> </PreferenceCategory>
<com.android.settingslib.widget.FooterPreference <com.android.settingslib.widget.FooterPreference
android:title="@string/location_settings_footer_location_on" android:title="@string/location_settings_footer_general"
android:key="location_footer" android:key="location_footer"
android:selectable="false" android:selectable="false"
settings:searchable="false"
settings:controller="com.android.settings.location.LocationSettingsFooterPreferenceController"/> settings:controller="com.android.settings.location.LocationSettingsFooterPreferenceController"/>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -54,7 +54,7 @@
settings:controller="com.android.settings.location.LocationServicesPreferenceController"/> settings:controller="com.android.settings.location.LocationServicesPreferenceController"/>
<com.android.settingslib.widget.FooterPreference <com.android.settingslib.widget.FooterPreference
android:title="@string/location_settings_footer_location_on" android:title="@string/location_settings_footer_general"
android:key="location_footer" android:key="location_footer"
settings:controller="com.android.settings.location.LocationSettingsFooterPreferenceController" settings:controller="com.android.settings.location.LocationSettingsFooterPreferenceController"
android:selectable="false"/> android:selectable="false"/>

View File

@@ -62,7 +62,7 @@
settings:controller="com.android.settings.location.LocationServicesForWorkPreferenceController"/> settings:controller="com.android.settings.location.LocationServicesForWorkPreferenceController"/>
<com.android.settingslib.widget.FooterPreference <com.android.settingslib.widget.FooterPreference
android:title="@string/location_settings_footer_location_on" android:title="@string/location_settings_footer_general"
android:key="location_footer" android:key="location_footer"
settings:controller="com.android.settings.location.LocationSettingsFooterPreferenceController" settings:controller="com.android.settings.location.LocationSettingsFooterPreferenceController"
android:selectable="false"/> android:selectable="false"/>

View File

@@ -59,12 +59,6 @@
</intent> </intent>
</Preference> </Preference>
<Preference
android:key="network_scorer_picker"
android:title="@string/network_scorer_picker_title"
android:fragment="com.android.settings.network.NetworkScorerPicker"
settings:controller="com.android.settings.network.NetworkScorerPickerPreferenceController" />
<Preference <Preference
android:key="wifi_direct" android:key="wifi_direct"
android:title="@string/wifi_menu_p2p" android:title="@string/wifi_menu_p2p"

View File

@@ -23,6 +23,7 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.provider.Settings; import android.provider.Settings;
import androidx.annotation.FloatRange;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
@@ -32,15 +33,18 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnResume;
/** Preference controller that controls the opacity seekbar in accessibility button page. */ /** Preference controller that controls the transparency seekbar in accessibility button page. */
public class FloatingMenuOpacityPreferenceController extends SliderPreferenceController public class FloatingMenuTransparencyPreferenceController extends SliderPreferenceController
implements LifecycleObserver, OnResume, OnPause { implements LifecycleObserver, OnResume, OnPause {
@VisibleForTesting @VisibleForTesting
static final float DEFAULT_OPACITY = 0.55f; @FloatRange(from = 0.0, to = 1.0)
static final float DEFAULT_TRANSPARENCY = 0.45f;
@VisibleForTesting
static final float MAXIMUM_TRANSPARENCY = 1.0f;
private static final int FADE_ENABLED = 1; private static final int FADE_ENABLED = 1;
private static final float MIN_PROGRESS = 10f; private static final float MIN_PROGRESS = 0f;
private static final float MAX_PROGRESS = 100f; private static final float MAX_PROGRESS = 90f;
@VisibleForTesting @VisibleForTesting
static final float PRECISION = 100f; static final float PRECISION = 100f;
@@ -51,7 +55,7 @@ public class FloatingMenuOpacityPreferenceController extends SliderPreferenceCon
@VisibleForTesting @VisibleForTesting
SeekBarPreference mPreference; SeekBarPreference mPreference;
public FloatingMenuOpacityPreferenceController(Context context, public FloatingMenuTransparencyPreferenceController(Context context,
String preferenceKey) { String preferenceKey) {
super(context, preferenceKey); super(context, preferenceKey);
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
@@ -101,15 +105,14 @@ public class FloatingMenuOpacityPreferenceController extends SliderPreferenceCon
@Override @Override
public int getSliderPosition() { public int getSliderPosition() {
return convertOpacityFloatToInt(getOpacity()); return convertTransparencyFloatToInt(getTransparency());
} }
@Override @Override
public boolean setSliderPosition(int position) { public boolean setSliderPosition(int position) {
final float value = convertOpacityIntToFloat(position); final float opacityValue = MAXIMUM_TRANSPARENCY - convertTransparencyIntToFloat(position);
return Settings.Secure.putFloat(mContentResolver, return Settings.Secure.putFloat(mContentResolver,
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, value); Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, opacityValue);
} }
@Override @Override
@@ -130,21 +133,21 @@ public class FloatingMenuOpacityPreferenceController extends SliderPreferenceCon
mPreference.setEnabled(AccessibilityUtil.isFloatingMenuEnabled(mContext) && fadeEnabled); mPreference.setEnabled(AccessibilityUtil.isFloatingMenuEnabled(mContext) && fadeEnabled);
} }
private int convertOpacityFloatToInt(float value) { private int convertTransparencyFloatToInt(float value) {
return Math.round(value * PRECISION); return Math.round(value * PRECISION);
} }
private float convertOpacityIntToFloat(int value) { private float convertTransparencyIntToFloat(int value) {
return (float) value / PRECISION; return (float) value / PRECISION;
} }
private float getOpacity() { private float getTransparency() {
float value = Settings.Secure.getFloat(mContentResolver, float transparencyValue = MAXIMUM_TRANSPARENCY - (Settings.Secure.getFloat(mContentResolver,
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, DEFAULT_OPACITY); Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, DEFAULT_TRANSPARENCY));
final float minValue = MIN_PROGRESS / PRECISION; final float minValue = MIN_PROGRESS / PRECISION;
final float maxValue = MAX_PROGRESS / PRECISION; final float maxValue = MAX_PROGRESS / PRECISION;
return (value < minValue || value > maxValue) ? DEFAULT_OPACITY : value; return (transparencyValue < minValue || transparencyValue > maxValue)
? DEFAULT_TRANSPARENCY : transparencyValue;
} }
} }

View File

@@ -52,6 +52,7 @@ import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType; import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import com.android.settings.utils.LocaleUtils;
import com.android.settings.widget.SettingsMainSwitchBar; import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settings.widget.SettingsMainSwitchPreference; import com.android.settings.widget.SettingsMainSwitchPreference;
import com.android.settingslib.accessibility.AccessibilityUtils; import com.android.settingslib.accessibility.AccessibilityUtils;
@@ -659,10 +660,9 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
if (list.isEmpty()) { if (list.isEmpty()) {
list.add(softwareTitle); list.add(softwareTitle);
} }
final String joinStrings = TextUtils.join(/* delimiter= */", ", list);
return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */ return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */
null, joinStrings); null, LocaleUtils.getConcatenatedString(list));
} }
/** /**

View File

@@ -46,6 +46,7 @@ import com.android.settings.DialogCreatable;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType; import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
import com.android.settings.utils.LocaleUtils;
import com.google.android.setupcompat.util.WizardManagerHelper; import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -282,10 +283,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends
if (list.isEmpty()) { if (list.isEmpty()) {
list.add(softwareTitle); list.add(softwareTitle);
} }
final String joinStrings = TextUtils.join(/* delimiter= */", ", list);
return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */ return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */
null, joinStrings); null, LocaleUtils.getConcatenatedString(list));
} }
@Override @Override

View File

@@ -58,7 +58,6 @@ public class AccountTypePreferenceLoader {
private static final String LAUNCHING_LOCATION_SETTINGS = private static final String LAUNCHING_LOCATION_SETTINGS =
"com.android.settings.accounts.LAUNCHING_LOCATION_SETTINGS"; "com.android.settings.accounts.LAUNCHING_LOCATION_SETTINGS";
private AuthenticatorHelper mAuthenticatorHelper; private AuthenticatorHelper mAuthenticatorHelper;
private UserHandle mUserHandle; private UserHandle mUserHandle;
private PreferenceFragmentCompat mFragment; private PreferenceFragmentCompat mFragment;

View File

@@ -107,6 +107,7 @@ public class SettingsBaseActivity extends FragmentActivity {
final int appliedTheme = ThemeHelper.isSetupWizardDayNightEnabled(this) final int appliedTheme = ThemeHelper.isSetupWizardDayNightEnabled(this)
? R.style.SubSettings_SetupWizard : R.style.SudThemeGlifV3_Light; ? R.style.SubSettings_SetupWizard : R.style.SudThemeGlifV3_Light;
setTheme(appliedTheme); setTheme(appliedTheme);
ThemeHelper.trySetDynamicColor(this);
} }
if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME) if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME)

View File

@@ -22,12 +22,8 @@ import android.app.Activity;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Process; import android.os.Process;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.IconDrawableFactory;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -38,7 +34,6 @@ import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -143,21 +138,8 @@ public class ActionDisabledByAdminDialogHelper {
@VisibleForTesting @VisibleForTesting
void setAdminSupportIcon(View root, ComponentName admin, int userId) { void setAdminSupportIcon(View root, ComponentName admin, int userId) {
ImageView supportIconView = root.requireViewById(R.id.admin_support_icon); ImageView supportIconView = root.requireViewById(R.id.admin_support_icon);
if (isNotCurrentUserOrProfile(admin, userId)) { supportIconView.setImageDrawable(
supportIconView.setImageDrawable( mActivity.getDrawable(com.android.internal.R.drawable.ic_corp_badge));
mActivity.getDrawable(com.android.internal.R.drawable.ic_info));
TypedArray ta = mActivity.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
supportIconView.setImageTintList(ColorStateList.valueOf(ta.getColor(0, 0)));
ta.recycle();
} else {
final Drawable badgedIcon = Utils.getBadgedIcon(
IconDrawableFactory.newInstance(mActivity),
mActivity.getPackageManager(),
admin.getPackageName(),
userId);
supportIconView.setImageDrawable(badgedIcon);
}
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -20,6 +20,7 @@ import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@@ -64,7 +65,6 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
ExpandDividerPreference.OnExpandListener { ExpandDividerPreference.OnExpandListener {
private static final String TAG = "BatteryChartPreferenceController"; private static final String TAG = "BatteryChartPreferenceController";
private static final String KEY_FOOTER_PREF = "battery_graph_footer"; private static final String KEY_FOOTER_PREF = "battery_graph_footer";
private static final int ADD_FOOTER_DELAYED_MS = 250;
/** Desired battery history size for timestamp slots. */ /** Desired battery history size for timestamp slots. */
public static final int DESIRED_HISTORY_SIZE = 25; public static final int DESIRED_HISTORY_SIZE = 25;
@@ -267,11 +267,6 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
void setBatteryHistoryMap( void setBatteryHistoryMap(
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) { final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
mHandler.post(() -> setBatteryHistoryMapInner(batteryHistoryMap));
}
private void setBatteryHistoryMapInner(
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
// Resets all battery history data relative variables. // Resets all battery history data relative variables.
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) { if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
mBatteryIndexedMap = null; mBatteryIndexedMap = null;
@@ -298,19 +293,15 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mBatteryHistoryLevels[index] = mBatteryHistoryLevels[index] =
Math.round(batteryLevelCounter / entryMap.size()); Math.round(batteryLevelCounter / entryMap.size());
} }
// Generates indexed usage map for chart.
mBatteryIndexedMap =
ConvertUtils.getIndexedUsageMap(
mPrefContext, /*timeSlotSize=*/ CHART_LEVEL_ARRAY_SIZE - 1,
mBatteryHistoryKeys, batteryHistoryMap,
/*purgeLowPercentageAndFakeData=*/ true);
forceRefreshUi(); forceRefreshUi();
Log.d(TAG, String.format( Log.d(TAG, String.format(
"setBatteryHistoryMap() size=%d\nkeys=%s\nlevels=%s", "setBatteryHistoryMap() size=%d\nkeys=%s\nlevels=%s",
batteryHistoryMap.size(), batteryHistoryMap.size(),
utcToLocalTime(mBatteryHistoryKeys), utcToLocalTime(mBatteryHistoryKeys),
Arrays.toString(mBatteryHistoryLevels))); Arrays.toString(mBatteryHistoryLevels)));
// Loads item icon and label in the background.
new LoadAllItemsInfoTask(batteryHistoryMap).execute();
} }
void setBatteryChartView(final BatteryChartView batteryChartView) { void setBatteryChartView(final BatteryChartView batteryChartView) {
@@ -599,9 +590,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
containAppItems containAppItems
? R.string.battery_usage_screen_footer ? R.string.battery_usage_screen_footer
: R.string.battery_usage_screen_footer_empty)); : R.string.battery_usage_screen_footer_empty));
mHandler.postDelayed( mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
() -> mPreferenceScreen.addPreference(mFooterPreference),
ADD_FOOTER_DELAYED_MS);
} }
private static String utcToLocalTime(long[] timestamps) { private static String utcToLocalTime(long[] timestamps) {
@@ -670,4 +659,53 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
} }
return batteryHistoryKeys; return batteryHistoryKeys;
} }
// Loads all items icon and label in the background.
private final class LoadAllItemsInfoTask
extends AsyncTask<Void, Void, Map<Integer, List<BatteryDiffEntry>>> {
private long[] mBatteryHistoryKeysCache;
private Map<Long, Map<String, BatteryHistEntry>> mBatteryHistoryMap;
private LoadAllItemsInfoTask(
Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
this.mBatteryHistoryMap = batteryHistoryMap;
this.mBatteryHistoryKeysCache = mBatteryHistoryKeys;
}
@Override
protected Map<Integer, List<BatteryDiffEntry>> doInBackground(Void... voids) {
if (mPrefContext == null || mBatteryHistoryKeysCache == null) {
return null;
}
final long startTime = System.currentTimeMillis();
final Map<Integer, List<BatteryDiffEntry>> indexedUsageMap =
ConvertUtils.getIndexedUsageMap(
mPrefContext, /*timeSlotSize=*/ CHART_LEVEL_ARRAY_SIZE - 1,
mBatteryHistoryKeysCache, mBatteryHistoryMap,
/*purgeLowPercentageAndFakeData=*/ true);
// Pre-loads each BatteryDiffEntry relative icon and label for all slots.
for (List<BatteryDiffEntry> entries : indexedUsageMap.values()) {
entries.forEach(entry -> entry.loadLabelAndIcon());
}
Log.d(TAG, String.format("execute LoadAllItemsInfoTask in %d/ms",
(System.currentTimeMillis() - startTime)));
return indexedUsageMap;
}
@Override
protected void onPostExecute(
Map<Integer, List<BatteryDiffEntry>> indexedUsageMap) {
mBatteryHistoryMap = null;
mBatteryHistoryKeysCache = null;
if (indexedUsageMap == null) {
return;
}
// Posts results back to main thread to refresh UI.
mHandler.post(() -> {
mBatteryIndexedMap = indexedUsageMap;
forceRefreshUi();
});
}
}
} }

View File

@@ -142,7 +142,7 @@ public class BatteryDiffEntry {
return false; return false;
} }
private void loadLabelAndIcon() { void loadLabelAndIcon() {
if (mIsLoaded) { if (mIsLoaded) {
return; return;
} }

View File

@@ -24,6 +24,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.location.LocationManager; import android.location.LocationManager;
import android.text.Html; import android.text.Html;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -42,6 +43,7 @@ import java.util.List;
*/ */
public class LocationSettingsFooterPreferenceController extends LocationBasePreferenceController { public class LocationSettingsFooterPreferenceController extends LocationBasePreferenceController {
private static final String TAG = "LocationFooter"; private static final String TAG = "LocationFooter";
private static final String PARAGRAPH_SEPARATOR = "<br><br>";
private static final Intent INJECT_INTENT = private static final Intent INJECT_INTENT =
new Intent(LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION); new Intent(LocationManager.SETTINGS_FOOTER_DISPLAYED_ACTION);
@@ -90,24 +92,33 @@ public class LocationSettingsFooterPreferenceController extends LocationBasePref
} }
private void updateFooterPreference() { private void updateFooterPreference() {
String footerString = mContext.getString( String footerString = mContext.getString(R.string.location_settings_footer_general);
mLocationEnabled ? R.string.location_settings_footer_location_on
: R.string.location_settings_footer_location_off);
if (mLocationEnabled) { if (mLocationEnabled) {
footerString = mInjectedFooterString + footerString; if (!TextUtils.isEmpty(mInjectedFooterString)) {
footerString = Html.escapeHtml(mInjectedFooterString) + PARAGRAPH_SEPARATOR
+ footerString;
}
} else {
footerString = mContext.getString(R.string.location_settings_footer_location_off)
+ PARAGRAPH_SEPARATOR
+ footerString;
} }
if (mFooterPreference != null) { if (mFooterPreference != null) {
mFooterPreference.setTitle(Html.fromHtml(footerString)); mFooterPreference.setTitle(Html.fromHtml(footerString
+ PARAGRAPH_SEPARATOR
+ mContext.getString(
R.string.location_settings_footer_learn_more)));
mFooterPreference.setContentDescription(Html.fromHtml(footerString + mContext.getString(
R.string.location_settings_footer_learn_more_content_description)));
} }
} }
/** /**
* Location footer preference group should be displayed if there is at least one footer to * Location footer preference group should always be displayed.
* inject.
*/ */
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
return !getFooterData().isEmpty() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; return AVAILABLE;
} }
/** /**

View File

@@ -1,145 +0,0 @@
/*
* Copyright (C) 2017 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.network;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settingslib.widget.RadioButtonPreference;
import java.util.List;
/**
* Fragment for choosing default network scorer.
*/
public class NetworkScorerPicker extends InstrumentedPreferenceFragment implements
RadioButtonPreference.OnClickListener {
private NetworkScoreManager mNetworkScoreManager;
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_NETWORK_SCORER;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
updateCandidates();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mNetworkScoreManager = createNetworkScorerManager(context);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = super.onCreateView(inflater, container, savedInstanceState);
// this is needed so the back button goes back to previous fragment
setHasOptionsMenu(true);
return view;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.network_scorer_picker_prefs;
}
@VisibleForTesting
public void updateCandidates() {
final PreferenceScreen screen = getPreferenceScreen();
screen.removeAll();
final List<NetworkScorerAppData> scorers = mNetworkScoreManager.getAllValidScorers();
final String defaultAppKey = getActiveScorerPackage();
final RadioButtonPreference nonePref = new RadioButtonPreference(getPrefContext());
nonePref.setTitle(R.string.network_scorer_picker_none_preference);
if (scorers.isEmpty()) {
nonePref.setChecked(true);
} else {
nonePref.setKey(null);
nonePref.setChecked(TextUtils.isEmpty(defaultAppKey));
nonePref.setOnClickListener(this);
}
screen.addPreference(nonePref);
final int numScorers = scorers.size();
for (int i = 0; i < numScorers; i++) {
final RadioButtonPreference pref = new RadioButtonPreference(getPrefContext());
final NetworkScorerAppData appData = scorers.get(i);
final String appKey = appData.getRecommendationServicePackageName();
pref.setTitle(appData.getRecommendationServiceLabel());
pref.setKey(appKey);
pref.setChecked(TextUtils.equals(defaultAppKey, appKey));
pref.setOnClickListener(this);
screen.addPreference(pref);
}
}
private String getActiveScorerPackage() {
return mNetworkScoreManager.getActiveScorerPackage();
}
private boolean setActiveScorer(String key) {
if (!TextUtils.equals(key, getActiveScorerPackage())) {
return mNetworkScoreManager.setActiveScorer(key);
}
return false;
}
@Override
public void onRadioButtonClicked(RadioButtonPreference selected) {
final String selectedKey = selected.getKey();
final boolean success = setActiveScorer(selectedKey);
if (success) {
updateCheckedState(selectedKey);
}
}
private void updateCheckedState(String selectedKey) {
final PreferenceScreen screen = getPreferenceScreen();
final int count = screen.getPreferenceCount();
for (int i = 0; i < count; i++) {
final Preference pref = screen.getPreference(i);
if (pref instanceof RadioButtonPreference) {
final RadioButtonPreference radioPref = (RadioButtonPreference) pref;
radioPref.setChecked(TextUtils.equals(pref.getKey(), selectedKey));
}
}
}
@VisibleForTesting
NetworkScoreManager createNetworkScorerManager(Context context) {
return (NetworkScoreManager) context.getSystemService(Context.NETWORK_SCORE_SERVICE);
}
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright (C) 2017 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.network;
import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import java.util.List;
/**
* {@link AbstractPreferenceController} that shows the active network scorer and toggles the
* preference based on whether or not there are valid scorers installed.
*/
public class NetworkScorerPickerPreferenceController extends BasePreferenceController {
private final NetworkScoreManager mNetworkScoreManager;
public NetworkScorerPickerPreferenceController(Context context, String key) {
super(context, key);
mNetworkScoreManager =
(NetworkScoreManager) mContext.getSystemService(Context.NETWORK_SCORE_SERVICE);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void updateState(Preference preference) {
final List<NetworkScorerAppData> allValidScorers =
mNetworkScoreManager.getAllValidScorers();
boolean enabled = !allValidScorers.isEmpty();
preference.setEnabled(enabled);
if (!enabled) {
preference.setSummary(null);
return;
}
NetworkScorerAppData scorer = mNetworkScoreManager.getActiveScorer();
if (scorer == null) {
preference.setSummary(mContext.getString(
R.string.network_scorer_picker_none_preference));
} else {
preference.setSummary(scorer.getRecommendationServiceLabel());
}
}
}

View File

@@ -153,7 +153,7 @@ public class RedactionInterstitial extends SettingsActivity {
} }
final RedactionInterstitial activity = (RedactionInterstitial) getActivity(); final RedactionInterstitial activity = (RedactionInterstitial) getActivity();
if (activity != null) { if (activity != null) {
activity.setResult(RESULT_OK, null); activity.setResult(RESULT_CANCELED, null);
finish(); finish();
} }
} }

View File

@@ -68,21 +68,10 @@ public class AllConversationsPreferenceController extends ConversationListPrefer
public void updateState(Preference preference) { public void updateState(Preference preference) {
PreferenceCategory pref = (PreferenceCategory) preference; PreferenceCategory pref = (PreferenceCategory) preference;
// Load conversations // Load conversations
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
mConversations = mBackend.getConversations(false).getList();
Collections.sort(mConversations, mConversationComparator);
return null;
}
@Override mConversations = mBackend.getConversations(false).getList();
protected void onPostExecute(Void unused) { Collections.sort(mConversations, mConversationComparator);
if (mContext == null) {
return; populateList(mConversations, pref);
}
populateList(mConversations, pref);
}
}.execute();
} }
} }

View File

@@ -63,7 +63,7 @@ public abstract class ConversationListPreferenceController extends AbstractPrefe
protected void populateList(List<ConversationChannelWrapper> conversations, protected void populateList(List<ConversationChannelWrapper> conversations,
PreferenceGroup containerGroup) { PreferenceGroup containerGroup) {
// TODO: if preference has children, compare with newly loaded list containerGroup.setVisible(false);
containerGroup.removeAll(); containerGroup.removeAll();
if (conversations != null) { if (conversations != null) {
populateConversations(conversations, containerGroup); populateConversations(conversations, containerGroup);
@@ -72,11 +72,11 @@ public abstract class ConversationListPreferenceController extends AbstractPrefe
if (containerGroup.getPreferenceCount() == 0) { if (containerGroup.getPreferenceCount() == 0) {
containerGroup.setVisible(false); containerGroup.setVisible(false);
} else { } else {
containerGroup.setVisible(true);
Preference summaryPref = getSummaryPreference(); Preference summaryPref = getSummaryPreference();
if (summaryPref != null) { if (summaryPref != null) {
containerGroup.addPreference(summaryPref); containerGroup.addPreference(summaryPref);
} }
containerGroup.setVisible(true);
} }
} }

View File

@@ -67,22 +67,9 @@ public class PriorityConversationsPreferenceController extends
public void updateState(Preference preference) { public void updateState(Preference preference) {
PreferenceCategory pref = (PreferenceCategory) preference; PreferenceCategory pref = (PreferenceCategory) preference;
// Load conversations // Load conversations
new AsyncTask<Void, Void, Void>() { mConversations = mBackend.getConversations(true).getList();
@Override Collections.sort(mConversations, mConversationComparator);
protected Void doInBackground(Void... unused) {
mConversations = mBackend.getConversations(true).getList();
Collections.sort(mConversations, mConversationComparator);
return null;
}
@Override
protected void onPostExecute(Void unused) {
if (mContext == null) {
return;
}
populateList(mConversations, pref);
}
}.execute();
populateList(mConversations, pref);
} }
} }

View File

@@ -104,26 +104,14 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC
public void updateState(Preference preference) { public void updateState(Preference preference) {
PreferenceCategory pref = (PreferenceCategory) preference; PreferenceCategory pref = (PreferenceCategory) preference;
// Load conversations // Load conversations
new AsyncTask<Void, Void, Void>() { try {
@Override mConversations = mPs.getRecentConversations().getList();
protected Void doInBackground(Void... unused) { } catch (RemoteException e) {
try { Slog.w(TAG, "Could get recents", e);
mConversations = mPs.getRecentConversations().getList(); }
} catch (RemoteException e) { Collections.sort(mConversations, mConversationComparator);
Slog.w(TAG, "Could get recents", e);
}
Collections.sort(mConversations, mConversationComparator);
return null;
}
@Override populateList(mConversations, pref);
protected void onPostExecute(Void unused) {
if (mContext == null) {
return;
}
populateList(mConversations, pref);
}
}.execute();
} }

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.utils;
import android.icu.text.ListFormatter;
import android.text.TextUtils;
import java.util.List;
import java.util.Locale;
/**
* This class implements some common methods to process with locales
*/
public class LocaleUtils {
/**
* Returns a character sequence concatenating the items with the localized comma.
*
* @param items items to be concatenated
*/
public static CharSequence getConcatenatedString(List<CharSequence> items) {
final ListFormatter listFormatter = ListFormatter.getInstance(Locale.getDefault());
final CharSequence lastItem = items.get(items.size() - 1);
items.add("fake last item");
// For English with "{0}, {1}, and {2}", the pattern is "{0}, {1}, and {2}".
// To get "{0}, {1}, {2}", we add a {fake item}, then the pattern result would be
// "{0}, {1}, {2} and {fake item}", then get the substring with the end index of the
// last item.
final String formatted = listFormatter.format(items);
return formatted.subSequence(0, TextUtils.indexOf(formatted, lastItem) + lastItem.length());
}
}

View File

@@ -19,8 +19,9 @@ package com.android.settings.accessibility;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR; import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
import static com.android.settings.accessibility.FloatingMenuOpacityPreferenceController.DEFAULT_OPACITY; import static com.android.settings.accessibility.FloatingMenuTransparencyPreferenceController.DEFAULT_TRANSPARENCY;
import static com.android.settings.accessibility.FloatingMenuOpacityPreferenceController.PRECISION; import static com.android.settings.accessibility.FloatingMenuTransparencyPreferenceController.MAXIMUM_TRANSPARENCY;
import static com.android.settings.accessibility.FloatingMenuTransparencyPreferenceController.PRECISION;
import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
@@ -47,9 +48,9 @@ import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
/** Tests for {@link FloatingMenuOpacityPreferenceController}. */ /** Tests for {@link FloatingMenuTransparencyPreferenceController}. */
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class FloatingMenuOpacityPreferenceControllerTest { public class FloatingMenuTransparencyPreferenceControllerTest {
@Rule @Rule
public MockitoRule mocks = MockitoJUnit.rule(); public MockitoRule mocks = MockitoJUnit.rule();
@@ -58,12 +59,12 @@ public class FloatingMenuOpacityPreferenceControllerTest {
private final Context mContext = ApplicationProvider.getApplicationContext(); private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock @Mock
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
private FloatingMenuOpacityPreferenceController mController; private FloatingMenuTransparencyPreferenceController mController;
@Before @Before
public void setUp() { public void setUp() {
when(mContext.getContentResolver()).thenReturn(mContentResolver); when(mContext.getContentResolver()).thenReturn(mContentResolver);
mController = new FloatingMenuOpacityPreferenceController(mContext, "test_key"); mController = new FloatingMenuTransparencyPreferenceController(mContext, "test_key");
} }
@Test @Test
@@ -95,10 +96,12 @@ public class FloatingMenuOpacityPreferenceControllerTest {
@Test @Test
public void getSliderPosition_putNormalOpacityValue_expectedValue() { public void getSliderPosition_putNormalOpacityValue_expectedValue() {
final float transparencyValue = 0.65f;
Settings.Secure.putFloat(mContext.getContentResolver(), Settings.Secure.putFloat(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, 0.35f); Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY,
(MAXIMUM_TRANSPARENCY - transparencyValue));
assertThat(mController.getSliderPosition()).isEqualTo(35); assertThat(mController.getSliderPosition()).isEqualTo((int) (transparencyValue * 100));
} }
@Test @Test
@@ -106,17 +109,18 @@ public class FloatingMenuOpacityPreferenceControllerTest {
Settings.Secure.putFloat(mContext.getContentResolver(), Settings.Secure.putFloat(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, 0.01f); Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, 0.01f);
final int defaultValue = Math.round(DEFAULT_OPACITY * PRECISION); final int defaultValue = Math.round(DEFAULT_TRANSPARENCY * PRECISION);
assertThat(mController.getSliderPosition()).isEqualTo(defaultValue); assertThat(mController.getSliderPosition()).isEqualTo(defaultValue);
} }
@Test @Test
public void setSliderPosition_expectedValue() { public void setSliderPosition_expectedValue() {
mController.setSliderPosition(27); final float transparencyValue = 0.27f;
mController.setSliderPosition((int) (transparencyValue * 100));
final float value = Settings.Secure.getFloat(mContext.getContentResolver(), final float value = Settings.Secure.getFloat(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, -1); Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, -1);
assertThat(value).isEqualTo(0.27f); assertThat(value).isEqualTo((MAXIMUM_TRANSPARENCY - transparencyValue));
} }
@Test @Test

View File

@@ -68,6 +68,7 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
private static final int BATTERY_LEVEL_50 = 50; private static final int BATTERY_LEVEL_50 = 50;
private static final String ICON_URI = "content://test.provider/icon.png"; private static final String ICON_URI = "content://test.provider/icon.png";
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C"; private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
private static final String DEVICE_SUMMARY = "test summary";
private Context mContext; private Context mContext;
@@ -133,7 +134,6 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
View.GONE); View.GONE);
assertThat(mLayoutPreference.findViewById(R.id.layout_middle).getVisibility()).isEqualTo( assertThat(mLayoutPreference.findViewById(R.id.layout_middle).getVisibility()).isEqualTo(
View.VISIBLE); View.VISIBLE);
assertBatteryLevel(mLayoutPreference.findViewById(R.id.layout_middle), BATTERY_LEVEL_MAIN);
} }
@Test @Test
@@ -232,67 +232,18 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
} }
@Test @Test
public void refresh_underLowBatteryThreshold_showAlertIcon() { public void refresh_connectedWatch_checkSummary() {
when(mBluetoothDevice.getMetadata( when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn( BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
BluetoothDevice.DEVICE_TYPE_WATCH.getBytes()); BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_BATTERY)).thenReturn(
String.valueOf(BATTERY_LEVEL_5).getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD)).thenReturn(
String.valueOf(LOW_BATTERY_LEVEL_THRESHOLD).getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_CHARGING)).thenReturn(
String.valueOf(false).getBytes());
when(mCachedDevice.isConnected()).thenReturn(true); when(mCachedDevice.isConnected()).thenReturn(true);
when(mCachedDevice.getConnectionSummary(/* shortSummary= */ true))
.thenReturn(DEVICE_SUMMARY);
mController.refresh(); mController.refresh();
assertBatteryIcon(mLayoutPreference.findViewById(R.id.layout_middle), assertThat(((TextView) (mLayoutPreference.findViewById(R.id.entity_header_summary)))
R.drawable.ic_battery_alert_24dp); .getText()).isEqualTo(DEVICE_SUMMARY);
}
@Test
public void refresh_underLowBatteryThresholdInCharging_showAlertIcon() {
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_BATTERY)).thenReturn(
String.valueOf(BATTERY_LEVEL_5).getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD)).thenReturn(
String.valueOf(LOW_BATTERY_LEVEL_THRESHOLD).getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_CHARGING)).thenReturn(
String.valueOf(true).getBytes());
when(mCachedDevice.isConnected()).thenReturn(true);
mController.refresh();
assertBatteryIcon(mLayoutPreference.findViewById(R.id.layout_middle), /* resId= */-1);
}
@Test
public void refresh_aboveLowBatteryThreshold_noAlertIcon() {
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_BATTERY)).thenReturn(
String.valueOf(BATTERY_LEVEL_50).getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_LOW_BATTERY_THRESHOLD)).thenReturn(
String.valueOf(LOW_BATTERY_LEVEL_THRESHOLD).getBytes());
when(mBluetoothDevice.getMetadata(
BluetoothDevice.METADATA_MAIN_CHARGING)).thenReturn(
String.valueOf(false).getBytes());
when(mCachedDevice.isConnected()).thenReturn(true);
mController.refresh();
assertBatteryIcon(mLayoutPreference.findViewById(R.id.layout_middle), /* resId= */-1);
} }
@Test @Test

View File

@@ -1,206 +0,0 @@
/*
* Copyright (C) 2017 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.network;
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.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.widget.RadioButtonPreference;
import com.google.android.collect.Lists;
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 java.util.ArrayList;
@RunWith(RobolectricTestRunner.class)
public class NetworkScorerPickerTest {
private static final String TEST_SCORER_PACKAGE_1 = "Test Package 1";
private static final String TEST_SCORER_CLASS_1 = "Test Class 1";
private static final String TEST_SCORER_LABEL_1 = "Test Label 1";
private static final String TEST_SCORER_PACKAGE_2 = "Test Package 2";
private Context mContext;
@Mock
private NetworkScoreManager mNetworkScoreManager;
@Mock
private PreferenceScreen mPreferenceScreen;
private TestFragment mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFragment = new TestFragment(mContext, mPreferenceScreen, mNetworkScoreManager);
mFragment.onAttach(mContext);
}
@Test
public void testOnRadioButtonClicked_success() {
RadioButtonPreference pref = new RadioButtonPreference(mContext);
pref.setKey(TEST_SCORER_PACKAGE_1);
when(mPreferenceScreen.getPreference(anyInt())).thenReturn(pref);
when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
when(mNetworkScoreManager.setActiveScorer(TEST_SCORER_PACKAGE_1)).thenReturn(true);
when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_2);
mFragment.onRadioButtonClicked(pref);
verify(mNetworkScoreManager).setActiveScorer(TEST_SCORER_PACKAGE_1);
assertThat(pref.isChecked()).isTrue();
}
@Test
public void testOnRadioButtonClicked_currentScorer_doNothing() {
RadioButtonPreference pref = new RadioButtonPreference(mContext);
pref.setKey(TEST_SCORER_PACKAGE_1);
pref.setChecked(true);
when(mPreferenceScreen.getPreference(anyInt())).thenReturn(pref);
when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
when(mNetworkScoreManager.setActiveScorer(TEST_SCORER_PACKAGE_1)).thenReturn(true);
when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);
mFragment.onRadioButtonClicked(pref);
verify(mNetworkScoreManager, never()).setActiveScorer(any());
assertThat(pref.isChecked()).isTrue();
}
@Test
public void testUpdateCandidates_noValidScorers_nonePreference() {
when(mNetworkScoreManager.getAllValidScorers()).thenReturn(new ArrayList<>());
ArgumentCaptor<RadioButtonPreference> arg =
ArgumentCaptor.forClass(RadioButtonPreference.class);
mFragment.updateCandidates();
verify(mPreferenceScreen).addPreference(arg.capture());
assertThat(arg.getValue().getTitle())
.isEqualTo(mContext.getString(R.string.network_scorer_picker_none_preference));
assertThat(arg.getValue().isChecked()).isTrue();
}
@Test
public void testUpdateCandidates_validScorers_noActiveScorer() {
ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE_1, TEST_SCORER_CLASS_1);
NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */,
null /* networkAvailableNotificationChannelId */);
when(mNetworkScoreManager.getAllValidScorers()).thenReturn(
Lists.newArrayList(scorerAppData));
when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(null);
ArgumentCaptor<RadioButtonPreference> arg =
ArgumentCaptor.forClass(RadioButtonPreference.class);
mFragment.updateCandidates();
verify(mPreferenceScreen, times(2)).addPreference(arg.capture());
final RadioButtonPreference nonePref = arg.getAllValues().get(0);
assertThat(nonePref.getKey()).isNull();
assertThat(nonePref.isChecked()).isTrue();
final RadioButtonPreference testScorerPref = arg.getAllValues().get(1);
assertThat(testScorerPref.getTitle()).isEqualTo(TEST_SCORER_LABEL_1);
assertThat(testScorerPref.isChecked()).isFalse();
}
@Test
public void testUpdateCandidates_validScorer() {
ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE_1, TEST_SCORER_CLASS_1);
NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
0, scorer, TEST_SCORER_LABEL_1, null /* enableUseOpenWifiActivity */,
null /* networkAvailableNotificationChannelId */);
when(mNetworkScoreManager.getAllValidScorers()).thenReturn(
Lists.newArrayList(scorerAppData));
when(mNetworkScoreManager.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_1);
ArgumentCaptor<RadioButtonPreference> arg =
ArgumentCaptor.forClass(RadioButtonPreference.class);
mFragment.updateCandidates();
// The first preference added is the "none" preference and the second is the
// pref for the test scorer.
verify(mPreferenceScreen, times(2)).addPreference(arg.capture());
// Returns the last captured value which is expected to be the test scorer pref.
RadioButtonPreference pref = arg.getValue();
assertThat(pref.getTitle()).isEqualTo(TEST_SCORER_LABEL_1);
assertThat(pref.isChecked()).isTrue();
}
public static class TestFragment extends NetworkScorerPicker {
private final Context mContext;
private final PreferenceScreen mScreen;
private final PreferenceManager mPrefManager;
private final NetworkScoreManager mNetworkScoreManager;
public TestFragment(Context context, PreferenceScreen preferenceScreen,
NetworkScoreManager networkScoreManager) {
mContext = context;
mScreen = preferenceScreen;
mNetworkScoreManager = networkScoreManager;
mPrefManager = mock(PreferenceManager.class);
when(mPrefManager.getContext()).thenReturn(context);
}
@Override
public Context getContext() {
return mContext;
}
@Override
public PreferenceManager getPreferenceManager() {
return mPrefManager;
}
@Override
public PreferenceScreen getPreferenceScreen() {
return mScreen;
}
@Override
NetworkScoreManager createNetworkScorerManager(Context context) {
return mNetworkScoreManager;
}
}
}

View File

@@ -1,148 +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.network;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
@RunWith(AndroidJUnit4.class)
public class NetworkScorerPickerPreferenceControllerTest {
private static final String TEST_SCORER_PACKAGE = "Test Package";
private static final String TEST_SCORER_CLASS = "Test Class";
private static final String TEST_SCORER_LABEL = "Test Label";
private Context mContext;
@Mock
private NetworkScoreManager mNetworkScorer;
private NetworkScorerPickerPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
doReturn(mNetworkScorer).when(mContext).getSystemService(Context.NETWORK_SCORE_SERVICE);
mController = new NetworkScorerPickerPreferenceController(mContext, "test_key");
}
@Test
public void testIsAvailable_shouldAlwaysReturnTrue() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void updateState_preferenceSetSummaryAsActiveScorerLabel() {
ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
null /* networkAvailableNotificationChannelId */);
when(mNetworkScorer.getAllValidScorers())
.thenReturn(Collections.singletonList(scorerAppData));
when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData);
Preference preference = mock(Preference.class);
mController.updateState(preference);
verify(preference).setSummary(TEST_SCORER_LABEL);
}
@Test
public void updateState_scorersAvailable_noActiveScorer_preferenceSetSummaryToNone() {
ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
null /* networkAvailableNotificationChannelId */);
when(mNetworkScorer.getAllValidScorers())
.thenReturn(Collections.singletonList(scorerAppData));
when(mNetworkScorer.getActiveScorer()).thenReturn(null);
Preference preference = mock(Preference.class);
mController.updateState(preference);
Context context = ApplicationProvider.getApplicationContext();
verify(preference).setSummary(
resourceString("network_scorer_picker_none_preference"));
}
@Test
public void updateState_scorersAvailable_preferenceEnabled() {
ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
null /* networkAvailableNotificationChannelId */);
when(mNetworkScorer.getAllValidScorers())
.thenReturn(Collections.singletonList(scorerAppData));
Preference preference = mock(Preference.class);
mController.updateState(preference);
verify(preference).setEnabled(true);
}
@Test
public void updateState_noScorersAvailable_preferenceDisabled() {
when(mNetworkScorer.getAllValidScorers())
.thenReturn(Collections.emptyList());
Preference preference = mock(Preference.class);
mController.updateState(preference);
verify(preference).setEnabled(false);
verify(preference).setSummary(null);
}
public int resourceId(String type, String name) {
return mContext.getResources().getIdentifier(name, type, mContext.getPackageName());
}
public String resourceString(String name) {
return mContext.getResources().getString(resourceId("string", name));
}
}