Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6324c21d authored by Jacky Wang's avatar Jacky Wang Committed by Android (Google) Code Review
Browse files

Merge changes from topic "catalyst" into main

* changes:
  [Catalyst] Use hybrid mode for sound screen
  [Catalyst] Use hybrid mode for display screen
  [Catalyst] Support hybrid mode
parents 6aebc96f d38549d6
Loading
Loading
Loading
Loading
+40 −4
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.preference.PreferenceScreenCreator;
import com.android.settingslib.search.Indexable;

import java.util.ArrayList;
@@ -60,6 +61,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -98,7 +100,8 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
        mDashboardFeatureProvider =
                FeatureFactory.getFeatureFactory().getDashboardFeatureProvider();

        if (!isCatalystEnabled()) {
        PreferenceScreenCreator preferenceScreenCreator = getPreferenceScreenCreator();
        if (preferenceScreenCreator == null || !preferenceScreenCreator.hasCompleteHierarchy()) {
            // Load preference controllers from code
            final List<AbstractPreferenceController> controllersFromCode =
                    createPreferenceControllers(context);
@@ -383,8 +386,12 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
            return;
        }
        PreferenceScreen screen;
        if (isCatalystEnabled()) {
        PreferenceScreenCreator preferenceScreenCreator = getPreferenceScreenCreator();
        if (preferenceScreenCreator != null) {
            screen = createPreferenceScreen();
            if (!preferenceScreenCreator.hasCompleteHierarchy()) {
                removeControllersForHybridMode();
            }
            setPreferenceScreen(screen);
            requireActivity().setTitle(screen.getTitle());
        } else {
@@ -395,13 +402,42 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
        displayResourceTilesToScreen(screen);
    }

    /**
     * Removes preference controllers that have been migrated to catalyst.
     *
     * In hybrid mode, preference screen is inflated from XML resource, while preference metadata
     * in the preference hierarchy are used to update preference widget UI. To avoid conflict,
     * remove the preference controllers.
     */
    private void removeControllersForHybridMode() {
        Set<String> keys = getPreferenceKeysInHierarchy();
        Iterator<AbstractPreferenceController> iterator = mControllers.iterator();
        while (iterator.hasNext()) {
            AbstractPreferenceController controller = iterator.next();
            String key = controller.getPreferenceKey();
            if (keys.contains(key)) {
                Log.i(TAG, "Remove preference controller for " + key);
                iterator.remove();
                List<AbstractPreferenceController> controllers = mPreferenceControllers.get(
                        controller.getClass());
                if (controllers != null) {
                    controllers.remove(controller);
                }
            }
        }
    }

    /** Returns if catalyst is enabled on current screen. */
    protected final boolean isCatalystEnabled() {
        return getPreferenceScreenCreator() != null;
    }

    private @Nullable PreferenceScreenCreator getPreferenceScreenCreator() {
        if (!Flags.catalyst()) {
            return false;
            return null;
        }
        Context context = getContext();
        return context != null ? getPreferenceScreenCreator(context) != null : false;
        return context != null ? getPreferenceScreenCreator(context) : null;
    }

    /**
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ class DisplayScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider {

    override fun isFlagEnabled(context: Context) = Flags.catalystDisplaySettingsScreen()

    override fun hasCompleteHierarchy() = false

    override fun fragmentClass() = DisplaySettings::class.java

    override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+4 −3
Original line number Diff line number Diff line
@@ -36,10 +36,11 @@ class SoundScreen : PreferenceScreenCreator {

    override fun isFlagEnabled(context: Context): Boolean = Flags.catalystSoundScreen()

    override fun hasCompleteHierarchy() = false

    override fun fragmentClass(): Class<out Fragment>? = SoundSettings::class.java

    override fun getPreferenceHierarchy(context: Context) =
        preferenceHierarchy(this) {}
    override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}

    companion object {
        const val KEY = "sound_screen"
+27 −7
Original line number Diff line number Diff line
@@ -17,24 +17,32 @@ package com.android.settings.display

import android.content.ContextWrapper
import android.content.res.Resources
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.internal.widget.LockPatternUtils
import com.android.settings.flags.Flags
import com.android.settings.testutils.FakeFeatureFactory
import com.android.settingslib.preference.CatalystScreenTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub

@RunWith(AndroidJUnit4::class)
class DisplayScreenTest {
    val preferenceScreenCreator = DisplayScreen()
class DisplayScreenTest : CatalystScreenTestCase() {

    override val preferenceScreenCreator = DisplayScreen()

    override val flagName: String
        get() = Flags.FLAG_CATALYST_DISPLAY_SETTINGS_SCREEN

    private val mockResources = mock<Resources>()

    private val context =
        object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
    private val contextWrapper =
        object : ContextWrapper(context) {
            override fun getResources(): Resources = mockResources
        }

@@ -47,13 +55,25 @@ class DisplayScreenTest {
    fun isAvailable_configTrue_shouldReturnTrue() {
        mockResources.stub { on { getBoolean(anyInt()) } doReturn true }

        assertThat(preferenceScreenCreator.isAvailable(context)).isTrue()
        assertThat(preferenceScreenCreator.isAvailable(contextWrapper)).isTrue()
    }

    @Test
    fun isAvailable_configFalse_shouldReturnFalse() {
        mockResources.stub { on { getBoolean(anyInt()) } doReturn false }

        assertThat(preferenceScreenCreator.isAvailable(context)).isFalse()
        assertThat(preferenceScreenCreator.isAvailable(contextWrapper)).isFalse()
    }

    override fun migration() {
        // avoid UnsupportedOperationException when getDisplay from context
        System.setProperty("robolectric.createActivityContexts", "true")

        val lockPatternUtils = mock<LockPatternUtils> { on { isSecure(anyInt()) } doReturn true }
        FakeFeatureFactory.setupForTest().securityFeatureProvider.stub {
            on { getLockPatternUtils(any()) } doReturn lockPatternUtils
        }

        super.migration()
    }
}
+8 −24
Original line number Diff line number Diff line
@@ -15,39 +15,23 @@
 */
package com.android.settings.notification

import android.content.Context
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.flags.Flags
import com.android.settingslib.preference.CatalystScreenTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class SoundScreenTest {
    @get:Rule val setFlagsRule = SetFlagsRule()
    private val context: Context = ApplicationProvider.getApplicationContext()
    private val soundScreen = SoundScreen()
class SoundScreenTest : CatalystScreenTestCase() {

    @Test
    fun key() {
        assertThat(soundScreen.key).isEqualTo(SoundScreen.KEY)
    }
    override val preferenceScreenCreator = SoundScreen()

    @Test
    @EnableFlags(Flags.FLAG_CATALYST_SOUND_SCREEN)
    fun isFlagEnabled_returnTrue() {
        assertThat(soundScreen.isFlagEnabled(context)).isTrue()
    }
    override val flagName: String
        get() = Flags.FLAG_CATALYST_SOUND_SCREEN

    @Test
    @DisableFlags(Flags.FLAG_CATALYST_SOUND_SCREEN)
    fun isFlagEnabled_returnFalse() {
        assertThat(soundScreen.isFlagEnabled(context)).isFalse()
    fun key() {
        assertThat(preferenceScreenCreator.key).isEqualTo(SoundScreen.KEY)
    }

}