Merge "Fine tune Caption size and style preview height for tablet" into tm-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 58ac9b7..4d3b6d0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2226,6 +2226,7 @@
 
         <activity android:name=".biometrics.BiometricEnrollActivity"
             android:exported="true"
+            android:configChanges="orientation|screenSize|keyboard|keyboardHidden|smallestScreenSize|screenLayout|density"
             android:theme="@style/GlifTheme.Light">
             <intent-filter>
                 <action android:name="android.settings.BIOMETRIC_ENROLL" />
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/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/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/FloatingMenuTransparencyPreferenceController.java b/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceController.java
index 894d3ae..9f698f2 100644
--- a/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceController.java
+++ b/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceController.java
@@ -51,9 +51,7 @@
     private final ContentResolver mContentResolver;
     @VisibleForTesting
     final ContentObserver mContentObserver;
-
-    @VisibleForTesting
-    SeekBarPreference mPreference;
+    private SeekBarPreference mPreference;
 
     public FloatingMenuTransparencyPreferenceController(Context context,
             String preferenceKey) {
@@ -83,6 +81,7 @@
         mPreference.setMin(getMin());
         mPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_ENDS);
 
+        updateAvailabilityStatus();
         updateState(mPreference);
     }
 
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/connecteddevice/usb/UsbConnectionBroadcastReceiver.java b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
index c5bcbed..c73c957 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
@@ -21,6 +21,7 @@
 import android.content.IntentFilter;
 import android.hardware.usb.UsbManager;
 import android.hardware.usb.UsbPortStatus;
+import android.util.Log;
 
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
@@ -31,6 +32,9 @@
  */
 public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements LifecycleObserver,
         OnResume, OnPause {
+    private static final String TAG = "UsbBroadcastReceiver";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
     private Context mContext;
     private UsbConnectionListener mUsbConnectionListener;
     private boolean mListeningToUsbEvents;
@@ -54,6 +58,9 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        if (DEBUG) {
+            Log.d(TAG, "onReceive() action : " + intent.getAction());
+        }
         if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
             mConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED)
                     || intent.getExtras().getBoolean(UsbManager.USB_HOST_CONNECTED);
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java
index ea1ccc0..d58e97b 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java
@@ -189,6 +189,8 @@
     @Override
     public void onPause() {
         super.onPause();
+        mCurrentFunctions = mUsbBackend.getCurrentFunctions();
+        Log.d(TAG, "onPause() : current functions : " + mCurrentFunctions);
         mUsbBackend.setDefaultUsbFunctions(mCurrentFunctions);
     }
 
diff --git a/src/com/android/settings/core/BasePreferenceController.java b/src/com/android/settings/core/BasePreferenceController.java
index 6cc09e2..5763d3b 100644
--- a/src/com/android/settings/core/BasePreferenceController.java
+++ b/src/com/android/settings/core/BasePreferenceController.java
@@ -126,7 +126,6 @@
     @Nullable
     private UserHandle mWorkProfileUser;
     private int mMetricsCategory;
-    private boolean mIsFirstLaunch;
     private boolean mPrefVisibility;
 
     /**
@@ -198,7 +197,6 @@
     public BasePreferenceController(Context context, String preferenceKey) {
         super(context);
         mPreferenceKey = preferenceKey;
-        mIsFirstLaunch = true;
         mPrefVisibility = true;
         if (TextUtils.isEmpty(mPreferenceKey)) {
             throw new IllegalArgumentException("Preference key must be set");
@@ -332,13 +330,6 @@
     }
 
     /**
-     * Set back the value of whether this is the first launch.
-     */
-    public void revokeFirstLaunch() {
-        mIsFirstLaunch = false;
-    }
-
-    /**
      * Launches the specified fragment for the work profile user if the associated
      * {@link Preference} is clicked.  Otherwise just forward it to the super class.
      *
@@ -454,7 +445,7 @@
      * preference visibility.
      */
     protected void updatePreferenceVisibilityDelegate(Preference preference, boolean isVisible) {
-        if (mUiBlockerFinished || !mIsFirstLaunch) {
+        if (mUiBlockerFinished) {
             preference.setVisible(isVisible);
             return;
         }
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 256a620..aaa9b3d 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -132,17 +132,22 @@
     @VisibleForTesting
     void checkUiBlocker(List<AbstractPreferenceController> controllers) {
         final List<String> keys = new ArrayList<>();
+        final List<BasePreferenceController> baseControllers = new ArrayList<>();
         controllers.forEach(controller -> {
             if (controller instanceof BasePreferenceController.UiBlocker
                     && controller.isAvailable()) {
                 ((BasePreferenceController) controller).setUiBlockListener(this);
                 keys.add(controller.getPreferenceKey());
+                baseControllers.add((BasePreferenceController) controller);
             }
         });
 
         if (!keys.isEmpty()) {
             mBlockerController = new UiBlockerController(keys);
-            mBlockerController.start(() -> updatePreferenceVisibility(mPreferenceControllers));
+            mBlockerController.start(() -> {
+                updatePreferenceVisibility(mPreferenceControllers);
+                baseControllers.forEach(controller -> controller.setUiBlockerFinished(true));
+            });
         }
     }
 
@@ -250,11 +255,6 @@
             }
             mListeningToCategoryChange = false;
         }
-        mControllers.forEach(controller -> {
-            if (controller instanceof BasePreferenceController.UiBlocker) {
-                ((BasePreferenceController) controller).revokeFirstLaunch();
-            }
-        });
     }
 
     @Override
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/ShowOperatorNamePreferenceController.java b/src/com/android/settings/display/ShowOperatorNamePreferenceController.java
index 40eaad3..9e9bf8e 100644
--- a/src/com/android/settings/display/ShowOperatorNamePreferenceController.java
+++ b/src/com/android/settings/display/ShowOperatorNamePreferenceController.java
@@ -14,12 +14,14 @@
 package com.android.settings.display;
 
 import android.content.Context;
+import android.os.PersistableBundle;
 import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
 
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
 
-import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.AbstractPreferenceController;
 
@@ -34,7 +36,15 @@
 
     @Override
     public boolean isAvailable() {
-        return mContext.getResources().getBoolean(R.bool.config_showOperatorNameInStatusBar);
+        final CarrierConfigManager configMgr = mContext
+                .getSystemService(CarrierConfigManager.class);
+        if (configMgr == null) {
+            return false;
+        }
+        final PersistableBundle b = configMgr.getConfigForSubId(SubscriptionManager
+                .getDefaultDataSubscriptionId());
+        return b != null && b.getBoolean(CarrierConfigManager
+                .KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL, false);
     }
 
     @Override
diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java b/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java
index 9fda03c..1b4e998 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() {
@@ -81,11 +82,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 +95,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 +111,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/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
index 743c7f9..f59dc60 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -26,13 +26,16 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
+import android.os.Binder;
 import android.os.Bundle;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.core.graphics.drawable.IconCompat;
@@ -49,8 +52,8 @@
 import com.android.settings.slices.CustomSliceable;
 import com.android.settings.slices.SliceBackgroundWorker;
 import com.android.settings.slices.SliceBuilderUtils;
+import com.android.settings.wifi.AppStateChangeWifiStateBridge;
 import com.android.settings.wifi.WifiDialogActivity;
-import com.android.settings.wifi.WifiSettings;
 import com.android.settings.wifi.WifiUtils;
 import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
 import com.android.wifitrackerlib.WifiEntry;
@@ -67,6 +70,7 @@
 
     @VisibleForTesting
     static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
+    private static final String TAG = "WifiSlice";
 
     protected final Context mContext;
     protected final WifiManager mWifiManager;
@@ -83,6 +87,12 @@
 
     @Override
     public Slice getSlice() {
+        // If external calling package doesn't have Wi-Fi permission.
+        if (!Utils.isSettingsIntelligence(mContext) && !isPermissionGranted(mContext)) {
+            Log.i(TAG, "No wifi permissions to control wifi slice.");
+            return null;
+        }
+
         final boolean isWifiEnabled = isWifiEnabled();
         ListBuilder listBuilder = getListBuilder(isWifiEnabled, null /* wifiSliceItem */);
         if (!isWifiEnabled) {
@@ -120,6 +130,30 @@
         return listBuilder.build();
     }
 
+    private static boolean isPermissionGranted(Context settingsContext) {
+        final int callingUid = Binder.getCallingUid();
+        final String callingPackage = settingsContext.getPackageManager()
+                .getPackagesForUid(callingUid)[0];
+
+        Context packageContext;
+        try {
+            packageContext = settingsContext.createPackageContext(callingPackage, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Cannot create Context for package: " + callingPackage);
+            return false;
+        }
+
+        // If app doesn't have related Wi-Fi permission, they shouldn't show Wi-Fi slice.
+        final boolean hasPermission = packageContext.checkPermission(
+                android.Manifest.permission.CHANGE_WIFI_STATE, Binder.getCallingPid(),
+                callingUid) == PackageManager.PERMISSION_GRANTED;
+        AppStateChangeWifiStateBridge.WifiSettingsState state =
+                new AppStateChangeWifiStateBridge(settingsContext, null, null)
+                        .getWifiSettingsInfo(callingPackage, callingUid);
+
+        return hasPermission && state.isPermissible();
+    }
+
     protected boolean isApRowCollapsed() {
         return false;
     }
@@ -175,7 +209,7 @@
             tint = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal);
         } else {
             tint = Utils.getDisabled(mContext, Utils.getColorAttrDefaultColor(mContext,
-                        android.R.attr.colorControlNormal));
+                    android.R.attr.colorControlNormal));
         }
 
         final Drawable drawable = mContext.getDrawable(
@@ -275,7 +309,7 @@
         final String key = WifiSwitchPreferenceController.KEY;
 
         final Intent intent = SliceBuilderUtils.buildSearchResultPageIntent(mContext, className,
-                key, screenTitle, SettingsEnums.DIALOG_WIFI_AP_EDIT, this)
+                        key, screenTitle, SettingsEnums.DIALOG_WIFI_AP_EDIT, this)
                 .setClassName(mContext.getPackageName(), SubSettings.class.getName())
                 .setData(contentUri);
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java
index 55637cd..eceb185 100644
--- a/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java
@@ -27,6 +27,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -34,6 +35,7 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.widget.SeekBarPreference;
@@ -60,11 +62,18 @@
     @Mock
     private ContentResolver mContentResolver;
     private FloatingMenuTransparencyPreferenceController mController;
+    private SeekBarPreference mSeekBarPreference;
+
+    @Mock
+    private PreferenceScreen mScreen;
 
     @Before
     public void setUp() {
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
         mController = new FloatingMenuTransparencyPreferenceController(mContext, "test_key");
+
+        mSeekBarPreference = new SeekBarPreference(mContext);
+        doReturn(mSeekBarPreference).when(mScreen).findPreference("test_key");
     }
 
     @Test
@@ -84,14 +93,67 @@
     }
 
     @Test
-    public void onChange_a11yBtnModeChangeToNavigationBar_preferenceDisabled() {
-        mController.mPreference = new SeekBarPreference(mContext);
+    public void displayPreference_floatingMenuMode_fadeEnabled_preferenceEnabled() {
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
+                ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
+        Settings.Secure.putInt(mContentResolver,
+                Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* ON */ 1);
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mSeekBarPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void displayPreference_floatingMenuMode_fadeDisabled_preferenceDisabled() {
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
+                ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
+        Settings.Secure.putInt(mContentResolver,
+                Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* OFF */ 0);
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mSeekBarPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void displayPreference_navigationBarMode_preferenceDisabled() {
         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
                 ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
 
+        mController.displayPreference(mScreen);
+
+        assertThat(mSeekBarPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void onChange_floatingMenuModeChangeToNavigationBar_preferenceDisabled() {
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
+                ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
+        Settings.Secure.putInt(mContentResolver,
+                Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* ON */ 1);
+        mController.displayPreference(mScreen);
+
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
+                ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
         mController.mContentObserver.onChange(false);
 
-        assertThat(mController.mPreference.isEnabled()).isFalse();
+        assertThat(mSeekBarPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void onChange_navigationBarModeChangeToFloatingMenu_preferenceDisabled() {
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
+                ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
+        Settings.Secure.putInt(mContentResolver,
+                Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, /* ON */ 1);
+        mController.displayPreference(mScreen);
+
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
+                ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
+        mController.mContentObserver.onChange(false);
+
+        assertThat(mSeekBarPreference.isEnabled()).isTrue();
     }
 
     @Test
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/connecteddevice/usb/UsbDefaultFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java
index 2317c97..9afc677 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java
@@ -205,6 +205,7 @@
         mFragment.mIsStartTethering = true;
         mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                 UsbManager.FUNCTION_RNDIS, POWER_ROLE_SINK, DATA_ROLE_DEVICE);
+        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_RNDIS);
 
         mFragment.onPause();
 
@@ -229,6 +230,7 @@
         mFragment.mIsStartTethering = true;
         mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                 UsbManager.FUNCTION_MTP, POWER_ROLE_SINK, DATA_ROLE_DEVICE);
+        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_MTP);
 
         mFragment.onPause();
 
@@ -241,6 +243,7 @@
         mFragment.mIsStartTethering = true;
         mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                 UsbManager.FUNCTION_PTP, POWER_ROLE_SINK, DATA_ROLE_DEVICE);
+        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_PTP);
 
         mFragment.onPause();
 
@@ -253,6 +256,7 @@
         mFragment.mIsStartTethering = true;
         mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                 UsbManager.FUNCTION_MIDI, POWER_ROLE_SINK, DATA_ROLE_DEVICE);
+        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_MIDI);
 
         mFragment.onPause();
 
@@ -265,6 +269,7 @@
         mFragment.mIsStartTethering = true;
         mFragment.mUsbConnectionListener.onUsbConnectionChanged(/* connected */ true,
                 UsbManager.FUNCTION_NCM, POWER_ROLE_SINK, DATA_ROLE_DEVICE);
+        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_NCM);
 
         mFragment.onPause();
 
diff --git a/tests/robotests/src/com/android/settings/display/ShowOperatorNamePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/ShowOperatorNamePreferenceControllerTest.java
index 9026c04..6a46110 100644
--- a/tests/robotests/src/com/android/settings/display/ShowOperatorNamePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/ShowOperatorNamePreferenceControllerTest.java
@@ -18,53 +18,62 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.os.PersistableBundle;
 import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
 
 import androidx.preference.SwitchPreference;
 
-import com.android.settings.R;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
 public class ShowOperatorNamePreferenceControllerTest {
 
     private static final String KEY_SHOW_OPERATOR_NAME = "show_operator_name";
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
     @Mock
     private SwitchPreference mPreference;
+    @Mock
+    private CarrierConfigManager mConfigManager;
 
     private ShowOperatorNamePreferenceController mController;
+    @Mock
+    private PersistableBundle mConfig;
+    private Context mContext;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+
+        when(mConfigManager.getConfigForSubId(anyInt())).thenReturn(mConfig);
+        when(mContext.getSystemService(CarrierConfigManager.class)).thenReturn(mConfigManager);
 
         mController = new ShowOperatorNamePreferenceController(mContext);
     }
 
     @Test
     public void testIsAvailable_configIsTrue_ReturnTrue() {
-        when(mContext.getResources()
-            .getBoolean(R.bool.config_showOperatorNameInStatusBar)).thenReturn(true);
+        when(mConfig.getBoolean(CarrierConfigManager
+                .KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL, false)).thenReturn(true);
         assertThat(mController.isAvailable()).isTrue();
     }
 
     @Test
     public void testIsAvailable_configIsFalse_ReturnFalse() {
-        when(mContext.getResources()
-            .getBoolean(R.bool.config_showOperatorNameInStatusBar)).thenReturn(false);
+        when(mConfig.getBoolean(CarrierConfigManager
+                .KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL, false)).thenReturn(false);
         assertThat(mController.isAvailable()).isFalse();
     }
 
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/robotests/src/com/android/settings/testutils/shadow/ShadowWifiSlice.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiSlice.java
new file mode 100644
index 0000000..ed583a4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiSlice.java
@@ -0,0 +1,39 @@
+/*
+ * 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.testutils.shadow;
+
+import android.content.Context;
+
+import com.android.settings.wifi.slice.WifiSlice;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(WifiSlice.class)
+public class ShadowWifiSlice {
+
+    private static boolean sIsWifiPermissible;
+
+    @Implementation
+    protected static boolean isPermissionGranted(Context settingsContext) {
+        return sIsWifiPermissible;
+    }
+
+    public static void setWifiPermissible(boolean isWifiPermissible) {
+        sIsWifiPermissible = isWifiPermissible;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
index f31c216..52dcb52 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
@@ -24,9 +24,11 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.wifi.WifiInfo;
@@ -44,6 +46,7 @@
 import com.android.settings.slices.SlicesFeatureProviderImpl;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowConnectivityManager;
+import com.android.settings.testutils.shadow.ShadowWifiSlice;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -53,17 +56,20 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowBinder;
 
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = ShadowConnectivityManager.class)
+@Config(shadows = {ShadowConnectivityManager.class, ShadowWifiSlice.class})
 public class ContextualWifiSliceTest {
     private static final String SSID = "123";
 
     @Mock
     private WifiManager mWifiManager;
     @Mock
+    private PackageManager mPackageManager;
+    @Mock
     private WifiInfo mWifiInfo;
     @Mock
     private Network mNetwork;
@@ -88,10 +94,16 @@
         doReturn(mWifiInfo).when(mWifiManager).getConnectionInfo();
         doReturn(SSID).when(mWifiInfo).getSSID();
         doReturn(mNetwork).when(mWifiManager).getCurrentNetwork();
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
 
         // Set-up specs for SliceMetadata.
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
 
+        final String siPackageName =
+                mContext.getString(R.string.config_settingsintelligence_package_name);
+        ShadowBinder.setCallingUid(1);
+        when(mPackageManager.getPackagesForUid(1)).thenReturn(new String[]{siPackageName});
+        ShadowWifiSlice.setWifiPermissible(true);
         mWifiSlice = new ContextualWifiSlice(mContext);
     }
 
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
index b4a8b05..5b7a7d6 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
@@ -31,21 +31,20 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
 
-import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
-import androidx.slice.SliceMetadata;
 import androidx.slice.SliceProvider;
-import androidx.slice.core.SliceAction;
 import androidx.slice.core.SliceQuery;
 import androidx.slice.widget.SliceLiveData;
 
 import com.android.settings.R;
 import com.android.settings.slices.SliceBackgroundWorker;
 import com.android.settings.testutils.SliceTester;
+import com.android.settings.testutils.shadow.ShadowWifiSlice;
 import com.android.wifitrackerlib.WifiEntry;
 import com.android.wifitrackerlib.WifiEntry.ConnectedState;
 
@@ -59,24 +58,32 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowBinder;
 
 import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = WifiSliceTest.ShadowSliceBackgroundWorker.class)
+@Config(shadows = {
+        WifiSliceTest.ShadowSliceBackgroundWorker.class,
+        ShadowWifiSlice.class})
 public class WifiSliceTest {
 
     private static final String AP1_NAME = "ap1";
     private static final String AP2_NAME = "ap2";
     private static final String AP3_NAME = "ap3";
+    private static final int USER_ID = 1;
 
     @Mock
     private WifiManager mWifiManager;
+    @Mock
+    private PackageManager mPackageManager;
+
 
     private Context mContext;
     private ContentResolver mResolver;
     private WifiSlice mWifiSlice;
+    private String mSIPackageName;
 
     @Before
     public void setUp() {
@@ -86,27 +93,46 @@
         doReturn(mResolver).when(mContext).getContentResolver();
         doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
         doReturn(WifiManager.WIFI_STATE_ENABLED).when(mWifiManager).getWifiState();
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
 
         // Set-up specs for SliceMetadata.
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
 
+        mSIPackageName = mContext.getString(R.string.config_settingsintelligence_package_name);
+        ShadowBinder.setCallingUid(USER_ID);
+        when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{mSIPackageName});
+        ShadowWifiSlice.setWifiPermissible(true);
         mWifiSlice = new WifiSlice(mContext);
     }
 
     @Test
-    public void getWifiSlice_shouldHaveTitleAndToggle() {
+    public void getWifiSlice_fromSIPackage_shouldHaveTitleAndToggle() {
+        when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{mSIPackageName});
+        ShadowWifiSlice.setWifiPermissible(false);
+
         final Slice wifiSlice = mWifiSlice.getSlice();
 
-        final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice);
-        assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.wifi_settings));
+        assertThat(wifiSlice).isNotNull();
+    }
 
-        final List<SliceAction> toggles = metadata.getToggles();
-        assertThat(toggles).hasSize(1);
+    @Test
+    public void getWifiSlice_notFromSIPackageAndWithWifiPermission_shouldHaveTitleAndToggle() {
+        when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{"com.test"});
+        ShadowWifiSlice.setWifiPermissible(true);
 
-        final SliceAction primaryAction = metadata.getPrimaryAction();
-        final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
-                R.drawable.ic_settings_wireless);
-        assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
+        final Slice wifiSlice = mWifiSlice.getSlice();
+
+        assertThat(wifiSlice).isNotNull();
+    }
+
+    @Test
+    public void getWifiSlice_notFromSIPackageAndWithoutWifiPermission_shouldNoSlice() {
+        when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{"com.test"});
+        ShadowWifiSlice.setWifiPermissible(false);
+
+        final Slice wifiSlice = mWifiSlice.getSlice();
+
+        assertThat(wifiSlice).isNull();
     }
 
     @Test
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;
+        }
+    }
+}