Merge "Import translations. DO NOT MERGE ANYWHERE" into tm-dev
diff --git a/res/layout/accessibility_text_reading_reset_button.xml b/res/layout/accessibility_text_reading_reset_button.xml
index f3691e1..a0bdcba 100644
--- a/res/layout/accessibility_text_reading_reset_button.xml
+++ b/res/layout/accessibility_text_reading_reset_button.xml
@@ -27,14 +27,11 @@
android:id="@+id/reset_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center|end"
+ android:layout_gravity="center_vertical|start"
android:paddingVertical="14dp"
- android:background="@null"
android:drawableStart="@drawable/ic_history"
android:drawablePadding="9dp"
- android:drawableTint="?android:attr/colorAccent"
- android:textColor="?android:attr/colorAccent"
- android:textSize="16sp"
- android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
- android:text="@string/accessibility_text_reading_reset_button_title"/>
+ android:drawableTint="@color/settingslib_btn_colored_text_material"
+ android:text="@string/accessibility_text_reading_reset_button_title"
+ style="@style/ActionPrimaryButton"/>
</FrameLayout>
diff --git a/res/layout/confirm_lock_password_base.xml b/res/layout/confirm_lock_password_base.xml
index 7c2fc5b..a3e5659 100644
--- a/res/layout/confirm_lock_password_base.xml
+++ b/res/layout/confirm_lock_password_base.xml
@@ -59,7 +59,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:inputType="textPassword"
- android:imeOptions="actionNext|flagForceAscii"
+ android:imeOptions="actionNext|flagForceAscii|flagNoExtractUi"
android:gravity="center"
style="@style/TextAppearance.PasswordEntry"/>
diff --git a/res/layout/confirm_lock_password_normal.xml b/res/layout/confirm_lock_password_normal.xml
index f2b8d1f..645c444 100644
--- a/res/layout/confirm_lock_password_normal.xml
+++ b/res/layout/confirm_lock_password_normal.xml
@@ -52,7 +52,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:inputType="textPassword"
- android:imeOptions="actionNext|flagForceAscii"
+ android:imeOptions="actionNext|flagForceAscii|flagNoExtractUi"
android:gravity="center"
style="@style/TextAppearance.PasswordEntry"/>
@@ -85,4 +85,4 @@
android:text="@string/cancel" />
</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
-</com.google.android.setupdesign.GlifLayout>
\ No newline at end of file
+</com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index 5e7a6a1..c497015 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -30,9 +30,7 @@
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
- android:orientation="vertical"
- android:layout_marginStart="?attr/sudMarginStart"
- android:layout_marginEnd="?attr/sudMarginEnd">
+ android:orientation="vertical">
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/error_text"
diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml
index aaed5be..5b4560e 100644
--- a/res/layout/fingerprint_enroll_introduction.xml
+++ b/res/layout/fingerprint_enroll_introduction.xml
@@ -30,9 +30,7 @@
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
- android:orientation="vertical"
- android:layout_marginStart="?attr/sudMarginStart"
- android:layout_marginEnd="?attr/sudMarginEnd">
+ android:orientation="vertical">
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/error_text"
diff --git a/res/layout/icon_discrete_slider.xml b/res/layout/icon_discrete_slider.xml
index b1d960f..47be5ef 100644
--- a/res/layout/icon_discrete_slider.xml
+++ b/res/layout/icon_discrete_slider.xml
@@ -19,6 +19,7 @@
android:id="@+id/seekbar_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipChildren="false"
android:background="?android:colorBackground"
android:gravity="center_vertical">
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 37e71e2..5248da6 100755
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -18,8 +18,6 @@
<dimen name="appwidget_width">421dip</dimen>
<dimen name="appwidget_height">68dip</dimen>
- <dimen name="captioning_preview_height">100dp</dimen>
-
<!-- ActionBar height -->
<dimen name="actionbar_size">46dip</dimen>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index 4e4a1d3..015a6af 100755
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -19,8 +19,6 @@
<dimen name="screen_margin_top">72dip</dimen>
<dimen name="screen_margin_bottom">48dip</dimen>
- <dimen name="captioning_preview_height">150dp</dimen>
-
<dimen name="confirm_credentials_top_padding">20dp</dimen>
<dimen name="confirm_credentials_top_margin">24dp</dimen>
diff --git a/res/values/config.xml b/res/values/config.xml
index 6b42baa..c7ef595 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -71,9 +71,6 @@
<!-- If the support features are enabled. -->
<bool name="config_support_enabled">false</bool>
- <!-- Whether to enable "show operator name in the status bar" setting -->
- <bool name="config_showOperatorNameInStatusBar">false</bool>
-
<!-- List containing the component names of pre-installed screen reader services. -->
<string-array name="config_preinstalled_screen_reader_services" translatable="false">
<!--
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b67bb22..c80e42c 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -49,7 +49,7 @@
<dimen name="pager_tabs_title_padding">16dp</dimen>
<dimen name="pager_tabs_selected_indicator_height">3dp</dimen>
- <dimen name="captioning_preview_height">200dp</dimen>
+ <dimen name="captioning_preview_height">300dp</dimen>
<dimen name="autoclick_preview_height">200dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cfcb62e..f87b489 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -98,10 +98,10 @@
<string name="font_size_make_larger_desc">Make larger</string>
<!-- Auto rotate switchbar title. [CHAR_LIMIT=NONE] -->
- <string name="auto_rotate_settings_primary_switch_title">Use Auto-rotate</string>
+ <string name="auto_rotate_settings_primary_switch_title">Use auto-rotate</string>
<!-- Disclaimer for camera based rotate [CHAR_LIMIT=NONE] -->
- <string name="smart_rotate_text_headline">Face Detection uses the front-facing camera to improve Auto-rotate accuracy. Images are never stored or sent to Google.</string>
+ <string name="smart_rotate_text_headline">Face Detection uses the front-facing camera to improve auto-rotate accuracy. Images are never stored or sent to Google.</string>
<string name="font_size_preview_text_headline">Sample text</string>
<string name="font_size_preview_text_title"
translation_description="Title text in sample text used to illustrate how the currently selected font size will appear to the user. NOTE: Translate manually. No not adopt any copyrighted material for translation.">
@@ -2926,7 +2926,13 @@
<!-- Sound & display settings screen, face-based rotation check box label [CHAR LIMIT=30] -->
<string name="auto_rotate_option_face_based">On - Face-based</string>
<!-- SmartAutoRotatePreferenceFragment settings screen, face-based rotation switch label [CHAR LIMIT=30] -->
- <string name="auto_rotate_switch_face_based">Enable Face Detection</string>
+ <string name="auto_rotate_switch_face_based">Face Detection</string>
+ <!-- Preference summary to enable auto rotate[CHAR_LIMIT=NONE]-->
+ <string name="auto_rotate_screen_summary">Automatically adjust the screen orientation when you move your phone between portrait and landscape</string>
+ <!-- Accessibility description for auto rotate learn more link [CHAR LIMIT=NONE] -->
+ <string name="auto_rotate_link_a11y">Learn more about auto-rotate</string>
+ <!-- Accessibility summary text for auto rotate [CHAR LIMIT=60] -->
+ <string name="auto_rotate_summary_a11y">When you move your phone between portrait and landscape</string>
<!-- Display settings screen, screen resolution settings title [CHAR LIMIT=30] -->
<string name="screen_resolution_title">Screen resolution</string>
@@ -5302,6 +5308,8 @@
<string name="accessibility_text_reading_preview_mail_content">Good morning!\n\nI just wanted to check how the designs are coming. Will they be ready before we start building the new balloons?</string>
<!-- Title for the reset button of the accessibility text reading page to reset all preferences state. [CHAR LIMIT=25] -->
<string name="accessibility_text_reading_reset_button_title">Reset settings</string>
+ <!-- Message for the toast after clicking the reset button of the dialog of the accessibility text reading page. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_text_reading_reset_message">Display size and text settings have been reset</string>
<!-- Title for the confirm dialog of reset settings. [CHAR LIMIT=NONE] -->
<string name="accessibility_text_reading_confirm_dialog_title">Reset display size and text?</string>
<!-- Message for the confirm dialog of reset settings. [CHAR LIMIT=NONE] -->
@@ -12453,6 +12461,9 @@
<!-- Help URI, battery saver page [DO NOT TRANSLATE] -->
<string name="help_url_battery_saver_settings" translatable="false"></string>
+ <!-- Help URI, auto rotate page [DO NOT TRANSLATE] -->
+ <string name="help_url_auto_rotate_settings" translatable="false"></string>
+
<!-- Help URI, app usage page [DO NOT TRANSLATE] -->
<string name="help_url_app_usage_settings" translatable="false"></string>
diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml
index f0be252..79adbd8 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -229,8 +229,6 @@
<item name="android:clipToPadding">true</item>
<item name="android:clipChildren">true</item>
<item name="android:textAppearanceListItem">@style/TextAppearance.PreferenceTitle.SettingsLib</item>
- <item name="android:listPreferredItemPaddingStart">@dimen/settingslib_listPreferredItemPaddingStart</item>
- <item name="android:listPreferredItemPaddingEnd">16dp</item>
<item name="preferenceTheme">@style/PreferenceTheme.SettingsLib</item>
<item name="android:switchStyle">@style/Switch.SettingsLib</item>
<item name="preferenceFragmentCompatStyle">@style/SetupWizardPreferenceFragmentStyle</item>
diff --git a/res/xml/accessibility_text_reading_options.xml b/res/xml/accessibility_text_reading_options.xml
index ad742c9..7fd5ff9 100644
--- a/res/xml/accessibility_text_reading_options.xml
+++ b/res/xml/accessibility_text_reading_options.xml
@@ -27,7 +27,7 @@
<com.android.settings.widget.LabeledSeekBarPreference
android:key="font_size"
- android:selectable="false"
+ android:selectable="true"
android:summary="@string/short_summary_font_size"
android:title="@string/title_font_size"
settings:iconEnd="@drawable/ic_add_24dp"
@@ -38,7 +38,7 @@
<com.android.settings.widget.LabeledSeekBarPreference
android:key="display_size"
- android:selectable="false"
+ android:selectable="true"
android:summary="@string/screen_zoom_short_summary"
android:title="@string/screen_zoom_title"
settings:iconEnd="@drawable/ic_add_24dp"
diff --git a/res/xml/auto_rotate_settings.xml b/res/xml/auto_rotate_settings.xml
index 0c120d6..38aa5f0 100644
--- a/res/xml/auto_rotate_settings.xml
+++ b/res/xml/auto_rotate_settings.xml
@@ -20,6 +20,14 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/accelerometer_title" >
+ <com.android.settingslib.widget.TopIntroPreference
+ android:title="@string/auto_rotate_screen_summary"/>
+
+ <com.android.settingslib.widget.MainSwitchPreference
+ android:key="auto_rotate_main_switch"
+ android:title="@string/auto_rotate_settings_primary_switch_title"
+ settings:controller="com.android.settings.display.AutoRotateSwitchBarController"/>
+
<SwitchPreference
android:key="auto_rotate_switch"
android:title="@string/auto_rotate_settings_primary_switch_title"
@@ -48,8 +56,9 @@
settings:controller="com.android.settings.display.SmartAutoRotateController" />
<com.android.settingslib.widget.FooterPreference
- android:icon="@drawable/ic_privacy_shield_24dp"
+ android:key="auto_rotate_footer_preference"
+ android:title="@string/smart_rotate_text_headline"
android:selectable="false"
- settings:searchable="false" />
+ settings:searchable="false"/>
</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/CaptionAppearanceFragment.java b/src/com/android/settings/accessibility/CaptionAppearanceFragment.java
index 13055be..53c1dd0 100644
--- a/src/com/android/settings/accessibility/CaptionAppearanceFragment.java
+++ b/src/com/android/settings/accessibility/CaptionAppearanceFragment.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
+import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
+
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
@@ -400,6 +402,7 @@
}
refreshPreviewText();
+ enableCaptioningManager();
}
@Override
@@ -409,16 +412,26 @@
Settings.Secure.putString(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE, (String) value);
refreshPreviewText();
+ enableCaptioningManager();
} else if (mFontSize == preference) {
Settings.Secure.putFloat(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE,
Float.parseFloat((String) value));
refreshPreviewText();
+ enableCaptioningManager();
}
return true;
}
+ private void enableCaptioningManager() {
+ if (mCaptioningManager.isEnabled()) {
+ return;
+ }
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, ON);
+ }
+
@Override
public int getHelpResource() {
return R.string.help_url_caption;
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
index 1148584..a4ee961c 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
+import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
@@ -178,6 +179,9 @@
} else {
mResetStateListeners.forEach(ResetStateListener::resetState);
}
+
+ Toast.makeText(getPrefContext(), R.string.accessibility_text_reading_reset_message,
+ Toast.LENGTH_SHORT).show();
}
private List<ResetStateListener> getResetStateListeners() {
diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
index 71f47cc..06f8276 100644
--- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
@@ -51,6 +51,11 @@
@Override
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
+ final boolean isEnabled = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON;
+ if (enabled == isEnabled) {
+ return;
+ }
+
if (enabled) {
showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
}
diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
index ac4408f..208d5c1 100644
--- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@@ -166,6 +166,11 @@
@Override
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
+ final boolean isEnabled = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON;
+ if (enabled == isEnabled) {
+ return;
+ }
+
if (enabled) {
showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index f0809ad..b7f8909 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -479,7 +479,7 @@
@Override
protected void refresh() {
for (LocalBluetoothProfile profile : getProfiles()) {
- if (!profile.isProfileReady()) {
+ if (profile != null && !profile.isProfileReady()) {
continue;
}
SwitchPreference pref = mProfilesContainer.findPreference(
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
index 8eb71df..96acd43 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
@@ -22,6 +22,7 @@
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.WindowManager;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
@@ -75,7 +76,12 @@
mRootView = LayoutInflater.from(builder.getContext())
.inflate(R.layout.dialog_sim_status, null /* parent */);
mController.initialize();
- return builder.setView(mRootView).create();
+
+ Dialog dlg = builder.setView(mRootView).create();
+ dlg.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
+ WindowManager.LayoutParams.FLAG_SECURE);
+
+ return dlg;
}
@Override
@@ -94,7 +100,7 @@
/**
* View ID(s) which is digit format (instead of decimal number) text.
**/
- private static final int [] sViewIdsInDigitFormat = IntStream
+ private static final int[] sViewIdsInDigitFormat = IntStream
.of(SimStatusDialogController.ICCID_INFO_VALUE_ID,
SimStatusDialogController.PHONE_NUMBER_VALUE_ID,
SimStatusDialogController.EID_INFO_VALUE_ID)
@@ -107,8 +113,7 @@
}
if (TextUtils.isEmpty(text)) {
text = getResources().getString(R.string.device_info_default);
- }
- else if (Arrays.binarySearch(sViewIdsInDigitFormat, viewId) >= 0) {
+ } else if (Arrays.binarySearch(sViewIdsInDigitFormat, viewId) >= 0) {
text = PhoneNumberUtil.expandByTts(text);
}
textView.setText(text);
diff --git a/src/com/android/settings/deviceinfo/storage/ManageStoragePreferenceController.java b/src/com/android/settings/deviceinfo/storage/ManageStoragePreferenceController.java
index 1a60cb8..9613b55 100644
--- a/src/com/android/settings/deviceinfo/storage/ManageStoragePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/ManageStoragePreferenceController.java
@@ -22,6 +22,7 @@
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.os.storage.StorageManager;
+import android.text.TextUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -65,6 +66,10 @@
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(getPreferenceKey(), preference.getKey())) {
+ return super.handlePreferenceTreeClick(preference);
+ }
+
final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
metricsFeatureProvider.action(mContext, SettingsEnums.STORAGE_FREE_UP_SPACE_NOW);
diff --git a/src/com/android/settings/display/AutoRotateSwitchBarController.java b/src/com/android/settings/display/AutoRotateSwitchBarController.java
index 48dedfd..d76104a 100644
--- a/src/com/android/settings/display/AutoRotateSwitchBarController.java
+++ b/src/com/android/settings/display/AutoRotateSwitchBarController.java
@@ -18,86 +18,78 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.widget.Switch;
import com.android.internal.view.RotationPolicy;
+import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.widget.SettingsMainSwitchBar;
+import com.android.settings.widget.SettingsMainSwitchPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
-import com.android.settingslib.widget.OnMainSwitchChangeListener;
/**
- * The switch controller for auto-rotate.
+ * The main switch controller for auto-rotate.
*/
-public class AutoRotateSwitchBarController implements OnMainSwitchChangeListener,
+public class AutoRotateSwitchBarController extends SettingsMainSwitchPreferenceController implements
LifecycleObserver, OnStart, OnStop {
- private final SettingsMainSwitchBar mSwitchBar;
- private final Context mContext;
- private boolean mValidListener;
private final MetricsFeatureProvider mMetricsFeatureProvider;
+ private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
- public AutoRotateSwitchBarController(Context context, SettingsMainSwitchBar switchBar,
- Lifecycle lifecycle) {
- mSwitchBar = switchBar;
- mContext = context;
+ public AutoRotateSwitchBarController(Context context, String key) {
+ super(context, key);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
- if (lifecycle != null) {
- lifecycle.addObserver(this);
- }
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return RotationPolicy.isRotationLockToggleVisible(mContext)
+ && !DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(mContext)
+ ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public void onStart() {
- if (!mValidListener) {
- mSwitchBar.addOnSwitchChangeListener(this);
- mValidListener = true;
+ if (mRotationPolicyListener == null) {
+ mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() {
+ @Override
+ public void onChange() {
+ if (mSwitchPreference != null) {
+ updateState(mSwitchPreference);
+ }
+ }
+ };
}
- onChange();
+ RotationPolicy.registerRotationPolicyListener(mContext,
+ mRotationPolicyListener);
}
@Override
public void onStop() {
- if (mValidListener) {
- mSwitchBar.removeOnSwitchChangeListener(this);
- mValidListener = false;
+ if (mRotationPolicyListener != null) {
+ RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
}
}
- /**
- * Listens to the state change of the rotation primary switch.
- */
@Override
- public void onSwitchChanged(Switch switchView, boolean isChecked) {
- setRotationLock(isChecked);
+ public boolean isChecked() {
+ return !RotationPolicy.isRotationLocked(mContext);
}
-
- protected void onChange() {
- final boolean isEnabled = !RotationPolicy.isRotationLocked(mContext);
- if (isEnabled != mSwitchBar.isChecked()) {
- // set listener to null so that that code below doesn't trigger onCheckedChanged()
- if (mValidListener) {
- mSwitchBar.removeOnSwitchChangeListener(this);
- }
- mSwitchBar.setChecked(isEnabled);
- if (mValidListener) {
- mSwitchBar.addOnSwitchChangeListener(this);
- }
- }
- }
-
- private boolean setRotationLock(boolean isChecked) {
+ @Override
+ public boolean setChecked(boolean isChecked) {
final boolean isLocked = !isChecked;
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATE_ROTATE_MASTER_TOGGLE,
- isChecked);
+ isLocked);
RotationPolicy.setRotationLock(mContext, isLocked);
return true;
}
+ @Override
+ public int getSliceHighlightMenuRes() {
+ return R.string.menu_key_display;
+ }
+
}
diff --git a/src/com/android/settings/display/SmartAutoRotateController.java b/src/com/android/settings/display/SmartAutoRotateController.java
index d29a64e..093c845 100644
--- a/src/com/android/settings/display/SmartAutoRotateController.java
+++ b/src/com/android/settings/display/SmartAutoRotateController.java
@@ -35,7 +35,6 @@
import android.service.rotationresolver.RotationResolverService;
import android.text.TextUtils;
-import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
@@ -82,10 +81,6 @@
context);
}
- public void init(Lifecycle lifecycle) {
- lifecycle.addObserver(this);
- }
-
@Override
public int getAvailabilityStatus() {
if (!isRotationResolverServiceAvailable(mContext)) {
diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java b/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java
index 9fda03c..36d3006 100644
--- a/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java
+++ b/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java
@@ -20,7 +20,7 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
-import android.text.Html;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -28,12 +28,11 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
-import com.android.internal.view.RotationPolicy;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.widget.SettingsMainSwitchBar;
+import com.android.settingslib.HelpUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
@@ -51,9 +50,11 @@
private static final String TAG = "SmartAutoRotatePreferenceFragment";
- private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
- private AutoRotateSwitchBarController mSwitchBarController;
- @VisibleForTesting static final String AUTO_ROTATE_SWITCH_PREFERENCE_ID = "auto_rotate_switch";
+ @VisibleForTesting
+ static final String AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY = "auto_rotate_main_switch";
+ @VisibleForTesting
+ static final String AUTO_ROTATE_SWITCH_PREFERENCE_KEY = "auto_rotate_switch";
+ private static final String KEY_FOOTER_PREFERENCE = "auto_rotate_footer_preference";
@Override
protected int getPreferenceScreenResId() {
@@ -63,7 +64,6 @@
@Override
public void onAttach(Context context) {
super.onAttach(context);
- use(SmartAutoRotateController.class).init(getLifecycle());
DeviceStateAutoRotationHelper.initControllers(
getLifecycle(),
useAll(DeviceStateAutoRotateSettingController.class)
@@ -81,11 +81,10 @@
final View view = super.onCreateView(inflater, container, savedInstanceState);
final SettingsActivity activity = (SettingsActivity) getActivity();
createHeader(activity);
- final Preference footerPreference = findPreference(FooterPreference.KEY_FOOTER);
+ final Preference footerPreference = findPreference(KEY_FOOTER_PREFERENCE);
if (footerPreference != null) {
- footerPreference.setTitle(Html.fromHtml(getString(R.string.smart_rotate_text_headline),
- Html.FROM_HTML_MODE_COMPACT));
footerPreference.setVisible(isRotationResolverServiceAvailable(activity));
+ setupFooter();
}
return view;
}
@@ -95,39 +94,9 @@
boolean deviceStateRotationEnabled =
DeviceStateAutoRotationHelper.isDeviceStateRotationEnabled(activity);
if (isRotationResolverServiceAvailable(activity) && !deviceStateRotationEnabled) {
- final SettingsMainSwitchBar switchBar = activity.getSwitchBar();
- switchBar.setTitle(
- getContext().getString(R.string.auto_rotate_settings_primary_switch_title));
- switchBar.show();
- mSwitchBarController = new AutoRotateSwitchBarController(activity, switchBar,
- getSettingsLifecycle());
- findPreference(AUTO_ROTATE_SWITCH_PREFERENCE_ID).setVisible(false);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (mRotationPolicyListener == null) {
- mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() {
- @Override
- public void onChange() {
- if (mSwitchBarController != null) {
- mSwitchBarController.onChange();
- }
- }
- };
- }
- RotationPolicy.registerRotationPolicyListener(getPrefContext(),
- mRotationPolicyListener);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- if (mRotationPolicyListener != null) {
- RotationPolicy.unregisterRotationPolicyListener(getPrefContext(),
- mRotationPolicyListener);
+ findPreference(AUTO_ROTATE_SWITCH_PREFERENCE_KEY).setVisible(false);
+ } else {
+ findPreference(AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY).setVisible(false);
}
}
@@ -141,6 +110,34 @@
return TAG;
}
+ @Override
+ public int getHelpResource() {
+ return R.string.help_url_auto_rotate_settings;
+ }
+
+ // Updates the footer for this page.
+ @VisibleForTesting
+ void setupFooter() {
+ final String mHelpUri = getString(getHelpResource());
+ if (!TextUtils.isEmpty(mHelpUri)) {
+ addHelpLink();
+ }
+ }
+
+ // Changes the text to include a learn more link if the link is defined.
+ @VisibleForTesting
+ void addHelpLink() {
+ final FooterPreference pref = findPreference(KEY_FOOTER_PREFERENCE);
+ if (pref != null) {
+ pref.setLearnMoreAction(v -> {
+ startActivityForResult(HelpUtils.getHelpIntent(getContext(),
+ getString(getHelpResource()),
+ /*backupContext=*/ ""), /*requestCode=*/ 0);
+ });
+ pref.setLearnMoreContentDescription(getString(R.string.auto_rotate_link_a11y));
+ }
+ }
+
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.auto_rotate_settings) {
diff --git a/src/com/android/settings/network/helper/LifecycleCallbackAdapter.java b/src/com/android/settings/network/helper/LifecycleCallbackAdapter.java
new file mode 100644
index 0000000..548eae5
--- /dev/null
+++ b/src/com/android/settings/network/helper/LifecycleCallbackAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.helper;
+
+import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleEventObserver;
+import androidx.lifecycle.LifecycleOwner;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * A {@link androidx.lifecycle.LifecycleObserver} implementation of adapter over callback.
+ *
+ * Which including:
+ * 1. Request to active callback when Lifecycle.State.STARTED
+ * 2. Request to inactive callback when Lifecycle.State.STOPPED
+ * 3. Close (no further resume) when Lifecycle.State.DESTROYED
+ */
+@VisibleForTesting
+abstract class LifecycleCallbackAdapter implements LifecycleEventObserver, AutoCloseable {
+ private static final String TAG = "LifecycleCallbackAdapter";
+ private AtomicReference<Lifecycle> mLifecycle = new AtomicReference<Lifecycle>();
+
+ /**
+ * Constructor
+ * @param lifecycle {@link Lifecycle} to monitor
+ */
+ @VisibleForTesting
+ protected LifecycleCallbackAdapter(@NonNull Lifecycle lifecycle) {
+ mLifecycle.set(lifecycle);
+ lifecycle.addObserver(this);
+ }
+
+ /**
+ * Get {@link Lifecycle} under monitor.
+ * @return {@link Lifecycle}. Return {@code null} when closed.
+ */
+ @VisibleForTesting
+ public Lifecycle getLifecycle() {
+ return mLifecycle.get();
+ }
+
+ /**
+ * Check current callback status.
+ * @return true when callback is active.
+ */
+ public abstract boolean isCallbackActive();
+
+ /**
+ * Change callback status.
+ * @param isActive true to active callback, otherwise inactive.
+ */
+ public abstract void setCallbackActive(boolean isActive);
+
+ /**
+ * Implementation of LifecycleEventObserver.
+ */
+ public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
+ if (mLifecycle.get() == null) {
+ return;
+ }
+
+ Lifecycle.State state = event.getTargetState();
+ boolean expectCallbackActive = state.isAtLeast(Lifecycle.State.STARTED);
+ if (expectCallbackActive != isCallbackActive()) {
+ setCallbackActive(expectCallbackActive);
+ }
+ if (state == Lifecycle.State.DESTROYED) {
+ close();
+ }
+ }
+
+ /**
+ * Implementation of AutoCloseable.
+ */
+ @MainThread
+ public void close() {
+ Lifecycle lifecycle = mLifecycle.getAndSet(null);
+ if (lifecycle != null) {
+ lifecycle.removeObserver(this);
+ }
+ }
+}
diff --git a/src/com/android/settings/network/helper/LifecycleCallbackConverter.java b/src/com/android/settings/network/helper/LifecycleCallbackConverter.java
new file mode 100644
index 0000000..f35b69a
--- /dev/null
+++ b/src/com/android/settings/network/helper/LifecycleCallbackConverter.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.helper;
+
+import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.UiThread;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
+
+/**
+ * A {@link LifecycleCallbackAdapter} which support carrying a result from any threads back to UI
+ * thread through {@link #postResult(T)}.
+ *
+ * A {@link Consumer<T>} would be invoked from UI thread for further processing on the result.
+ *
+ * Note: Result not in STARTED or RESUMED stage will be discarded silently.
+ * This is to align with the criteria set within
+ * {@link LifecycleCallbackAdapter#onStateChanged()}.
+ */
+@VisibleForTesting
+public class LifecycleCallbackConverter<T> extends LifecycleCallbackAdapter {
+ private static final String TAG = "LifecycleCallbackConverter";
+
+ private final Thread mUiThread;
+ private final Consumer<T> mResultCallback;
+
+ /**
+ * A record of number of active status change.
+ * Even numbers (0, 2, 4, 6 ...) are inactive status.
+ * Odd numbers (1, 3, 5, 7 ...) are active status.
+ */
+ private final AtomicLong mNumberOfActiveStatusChange = new AtomicLong();
+
+ /**
+ * Constructor
+ *
+ * @param lifecycle {@link Lifecycle} to monitor
+ * @param resultCallback for further processing the result
+ */
+ @VisibleForTesting
+ @UiThread
+ public LifecycleCallbackConverter(
+ @NonNull Lifecycle lifecycle, @NonNull Consumer<T> resultCallback) {
+ super(lifecycle);
+ mUiThread = Thread.currentThread();
+ mResultCallback = resultCallback;
+ }
+
+ /**
+ * Post a result (from any thread) back to UI thread.
+ *
+ * @param result the object ready to be passed back to {@link Consumer<T>}.
+ */
+ @AnyThread
+ @VisibleForTesting
+ public void postResult(T result) {
+ /**
+ * Since mNumberOfActiveStatusChange only increase, it is a concept of sequence number.
+ * Carry it when sending data in between different threads allow to verify if the data
+ * has arrived on time. And drop the data when expired.
+ */
+ long currentNumberOfChange = mNumberOfActiveStatusChange.get();
+ if (Thread.currentThread() == mUiThread) {
+ dispatchExtResult(currentNumberOfChange, result); // Dispatch directly
+ } else {
+ postResultToUiThread(currentNumberOfChange, result);
+ }
+ }
+
+ @AnyThread
+ protected void postResultToUiThread(long numberOfStatusChange, T result) {
+ ThreadUtils.postOnMainThread(() -> dispatchExtResult(numberOfStatusChange, result));
+ }
+
+ @UiThread
+ protected void dispatchExtResult(long numberOfStatusChange, T result) {
+ /**
+ * For a postResult() sending in between different threads, not only create a latency
+ * but also enqueued into main UI thread for dispatch.
+ *
+ * To align behavior within {@link LifecycleCallbackAdapter#onStateChanged()},
+ * some checking on both numberOfStatusChange and {@link Lifecycle} status are required.
+ */
+ if (isActiveStatus(numberOfStatusChange)
+ && (numberOfStatusChange == mNumberOfActiveStatusChange.get())
+ && getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
+ mResultCallback.accept(result);
+ }
+ }
+
+ private static final boolean isActiveStatus(long numberOfStatusChange) {
+ return ((numberOfStatusChange & 1L) != 0L);
+ }
+
+ /* Implementation of LifecycleCallbackAdapter */
+ @UiThread
+ public boolean isCallbackActive() {
+ return isActiveStatus(mNumberOfActiveStatusChange.get());
+ }
+
+ /* Implementation of LifecycleCallbackAdapter */
+ @UiThread
+ public void setCallbackActive(boolean updatedActiveStatus) {
+ /**
+ * Make sure only increase when active status got changed.
+ * This is to implement the definition of mNumberOfActiveStatusChange.
+ */
+ if (isCallbackActive() != updatedActiveStatus) {
+ mNumberOfActiveStatusChange.getAndIncrement();
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentTest.java
index 1793cc2..b72cdf7 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentTest.java
@@ -47,6 +47,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowToast;
import java.util.ArrayList;
import java.util.Arrays;
@@ -104,4 +105,18 @@
verify(listener1).resetState();
verify(listener2).resetState();
}
+
+ @Test
+ public void onDialogPositiveButtonClicked_boldTextEnabled_showToast() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.FONT_WEIGHT_ADJUSTMENT, BOLD_TEXT_ADJUSTMENT);
+ final AlertDialog dialog = (AlertDialog) mFragment.onCreateDialog(
+ DialogEnums.DIALOG_RESET_SETTINGS);
+ dialog.show();
+
+ dialog.getButton(DialogInterface.BUTTON_POSITIVE).callOnClick();
+
+ assertThat(ShadowToast.getTextOfLatestToast())
+ .isEqualTo(mContext.getString(R.string.accessibility_text_reading_reset_message));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java
index 942fed6..e537419 100644
--- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java
@@ -16,7 +16,8 @@
package com.android.settings.display;
-import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_SWITCH_PREFERENCE_ID;
+import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY;
+import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_SWITCH_PREFERENCE_KEY;
import static com.google.common.truth.Truth.assertThat;
@@ -45,7 +46,6 @@
import com.android.settings.testutils.ResolveInfoBuilder;
import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager;
import com.android.settings.testutils.shadow.ShadowRotationPolicy;
-import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
@@ -71,8 +71,6 @@
private SmartAutoRotatePreferenceFragment mFragment;
- private SettingsMainSwitchBar mSwitchBar;
-
@Mock
private PackageManager mPackageManager;
@@ -87,6 +85,9 @@
private Resources mResources;
private Context mContext;
+ @Mock
+ private Preference mRotateMainSwitchPreference;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -112,21 +113,21 @@
when(mFragment.getContext()).thenReturn(mContext);
doReturn(mView).when(mFragment).getView();
- when(mFragment.findPreference(AUTO_ROTATE_SWITCH_PREFERENCE_ID)).thenReturn(
+ when(mFragment.findPreference(AUTO_ROTATE_SWITCH_PREFERENCE_KEY)).thenReturn(
mRotateSwitchPreference);
- mSwitchBar = spy(new SettingsMainSwitchBar(mContext));
- when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
- doReturn(mSwitchBar).when(mView).findViewById(R.id.switch_bar);
- ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false);
+
+ when(mFragment.findPreference(AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY)).thenReturn(
+ mRotateMainSwitchPreference);
}
@Test
public void createHeader_faceDetectionSupported_switchBarIsEnabled() {
+ ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false);
mFragment.createHeader(mActivity);
- verify(mSwitchBar, times(1)).show();
+ verify(mRotateMainSwitchPreference, never()).setVisible(false);
verify(mRotateSwitchPreference, times(1)).setVisible(false);
}
@@ -137,7 +138,7 @@
mFragment.createHeader(mActivity);
- verify(mSwitchBar, never()).show();
+ verify(mRotateMainSwitchPreference, times(1)).setVisible(false);
verify(mRotateSwitchPreference, never()).setVisible(false);
}
@@ -147,7 +148,7 @@
mFragment.createHeader(mActivity);
- verify(mSwitchBar, never()).show();
+ verify(mRotateMainSwitchPreference, times(1)).setVisible(false);
verify(mRotateSwitchPreference, never()).setVisible(false);
}
@@ -176,6 +177,19 @@
DeviceStateAutoRotateSettingController.class);
}
+ @Test
+ public void setupFooter_linkAddedWhenAppropriate() {
+ doReturn("").when(mFragment).getText(anyInt());
+ doReturn("").when(mFragment).getString(anyInt());
+ mFragment.setupFooter();
+ verify(mFragment, never()).addHelpLink();
+
+ doReturn("testString").when(mFragment).getText(anyInt());
+ doReturn("testString").when(mFragment).getString(anyInt());
+ mFragment.setupFooter();
+ verify(mFragment, times(1)).addHelpLink();
+ }
+
private void enableDeviceStateSettableRotationStates(String[] settableStates,
String[] settableStatesDescriptions) {
when(mResources.getStringArray(
diff --git a/tests/unit/src/com/android/settings/deviceinfo/storage/ManageStoragePreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/storage/ManageStoragePreferenceControllerTest.java
new file mode 100644
index 0000000..6806bdd
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/storage/ManageStoragePreferenceControllerTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.storage;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.widget.CardPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class ManageStoragePreferenceControllerTest {
+
+ private ManageStoragePreferenceController mController;
+ private CardPreference mPreference;
+
+ @Before
+ public void setUp() {
+ Context context = ApplicationProvider.getApplicationContext();
+ mPreference = new CardPreference(context);
+ mController = new ManageStoragePreferenceController(context, "free_up_space");
+ }
+
+ @Test
+ public void handPreferenceTreeClick_keyMatched_consumeClickEvent() {
+ mPreference.setKey(mController.getPreferenceKey());
+
+ assertTrue(mController.handlePreferenceTreeClick(mPreference));
+ }
+
+ @Test
+ public void handPreferenceTreeClick_keyNotMatched_notConsumeClickEvent() {
+ mPreference.setKey("not_matched_key");
+
+ assertFalse(mController.handlePreferenceTreeClick(mPreference));
+ }
+}
diff --git a/tests/unit/src/com/android/settings/network/helper/LifecycleCallbackAdapterTest.java b/tests/unit/src/com/android/settings/network/helper/LifecycleCallbackAdapterTest.java
new file mode 100644
index 0000000..ddeb3f8
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/helper/LifecycleCallbackAdapterTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.network.helper;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class LifecycleCallbackAdapterTest implements LifecycleOwner {
+
+ private final LifecycleRegistry mRegistry = LifecycleRegistry.createUnsafe(this);
+
+ private TestObj mTarget;
+
+ @Before
+ public void setUp() {
+ mTarget = new TestObj(getLifecycle());
+ }
+
+ public Lifecycle getLifecycle() {
+ return mRegistry;
+ }
+
+ @Test
+ public void lifecycle_get_lifecycleToMonitor() {
+ assertThat(mTarget.getLifecycle()).isEqualTo(mRegistry);
+ }
+
+ @Test
+ public void lifecycle_stateChangeToStart_callbackActive() {
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+
+ assertThat(mTarget.getCallbackCount()).isEqualTo(0);
+ assertThat(mTarget.isCallbackActive()).isEqualTo(Boolean.FALSE);
+
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+
+ assertThat(mTarget.getCallbackCount()).isEqualTo(1);
+ assertThat(mTarget.isCallbackActive()).isEqualTo(Boolean.TRUE);
+ }
+
+ @Test
+ public void lifecycle_stateChangeToStop_callbackInActive() {
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
+
+ assertThat(mTarget.getCallbackCount()).isEqualTo(2);
+ assertThat(mTarget.isCallbackActive()).isEqualTo(Boolean.FALSE);
+ }
+
+ @Test
+ public void lifecycle_stateChangeToDestroy_noFurtherActive() {
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
+
+ assertThat(mTarget.getCallbackCount()).isEqualTo(2);
+ assertThat(mTarget.isCallbackActive()).isEqualTo(Boolean.FALSE);
+
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+
+ assertThat(mTarget.getCallbackCount()).isEqualTo(2);
+ assertThat(mTarget.isCallbackActive()).isEqualTo(Boolean.FALSE);
+ }
+
+ public static class TestObj extends LifecycleCallbackAdapter {
+ boolean mIsActive;
+ int mNumberOfCallback;
+
+ public TestObj(Lifecycle lifecycle) {
+ super(lifecycle);
+ }
+
+ public boolean isCallbackActive() {
+ return mIsActive;
+ }
+
+ public void setCallbackActive(boolean isActive) {
+ mIsActive = isActive;
+ mNumberOfCallback ++;
+ }
+
+ protected int getCallbackCount() {
+ return mNumberOfCallback;
+ }
+ }
+}
diff --git a/tests/unit/src/com/android/settings/network/helper/LifecycleCallbackConverterTest.java b/tests/unit/src/com/android/settings/network/helper/LifecycleCallbackConverterTest.java
new file mode 100644
index 0000000..149fd8293
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/helper/LifecycleCallbackConverterTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.network.helper;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Phaser;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+@RunWith(AndroidJUnit4.class)
+public class LifecycleCallbackConverterTest implements LifecycleOwner {
+
+ private final LifecycleRegistry mRegistry = LifecycleRegistry.createUnsafe(this);
+
+ private Object mTestData;
+ private TestConsumer mConsumer;
+ private LifecycleCallbackConverter<Object> mConverter;
+
+ @Before
+ public void setUp() {
+ mTestData = new Object();
+ mConsumer = new TestConsumer();
+ mConverter = new LifecycleCallbackConverter<Object>(getLifecycle(), mConsumer);
+ }
+
+ public Lifecycle getLifecycle() {
+ return mRegistry;
+ }
+
+ @Test
+ public void converter_dropResult_whenInActive() {
+ mConverter.postResult(mTestData);
+
+ assertThat(mConsumer.getCallbackCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void converter_callbackResult_whenActive() {
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+
+ mConverter.postResult(mTestData);
+ assertThat(mConsumer.getCallbackCount()).isEqualTo(1);
+ assertThat(mConsumer.getData()).isEqualTo(mTestData);
+ }
+
+ @Test
+ public void converter_dropResult_whenBackToInActive() {
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
+
+ mConverter.postResult(mTestData);
+ assertThat(mConsumer.getCallbackCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void converter_passResultToUiThread_whenActive() {
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+
+ final Phaser phaser = new Phaser(1);
+ Thread executionThread = new Thread(() -> {
+ mConverter.postResult(phaser);
+ });
+ executionThread.start();
+ phaser.awaitAdvance(0);
+
+ assertThat(mConsumer.getData()).isEqualTo(phaser);
+ assertThat(mConsumer.getCallbackCount()).isEqualTo(1);
+ }
+
+ public static class TestConsumer implements Consumer<Object> {
+ long mNumberOfCallback;
+ AtomicReference<Object> mLatestData;
+
+ public TestConsumer() {
+ mLatestData = new AtomicReference<Object>();
+ }
+
+ public void accept(Object data) {
+ mLatestData.set(data);
+ mNumberOfCallback ++;
+ if ((data != null) && (data instanceof Phaser)) {
+ ((Phaser)data).arrive();
+ }
+ }
+
+ protected long getCallbackCount() {
+ return mNumberOfCallback;
+ }
+
+ protected Object getData() {
+ return mLatestData.get();
+ }
+ }
+}