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

Commit ad3c9b17 authored by Alex Florescu's avatar Alex Florescu
Browse files

Don't disable QS when in split shade

Drive-by test refactor and kotlin converstion.

Fixes: 193375549
Test: atest SystemUITests:RemoteInputQuickSettingsDisablerTest
Change-Id: Icc07afcc5f843190c1519f19d067ddaf80a523b8
parent a93b661b
Loading
Loading
Loading
Loading
+0 −86
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.systemui.statusbar.policy;

import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBar;

import javax.inject.Inject;

/**
 * Let {@link RemoteInputView} to control the visibility of QuickSetting.
 */
@SysUISingleton
public class RemoteInputQuickSettingsDisabler
        implements ConfigurationController.ConfigurationListener {

    private Context mContext;
    @VisibleForTesting boolean mRemoteInputActive;
    @VisibleForTesting boolean misLandscape;
    private int mLastOrientation;
    private final CommandQueue mCommandQueue;

    @Inject
    public RemoteInputQuickSettingsDisabler(Context context,
            ConfigurationController configController, CommandQueue commandQueue) {
        mContext = context;
        mCommandQueue = commandQueue;
        mLastOrientation = mContext.getResources().getConfiguration().orientation;
        configController.addCallback(this);
    }

    public int adjustDisableFlags(int state) {
        if (mRemoteInputActive && misLandscape) {
            state |= StatusBarManager.DISABLE2_QUICK_SETTINGS;
        }

        return state;
    }

    public void setRemoteInputActive(boolean active){
        if(mRemoteInputActive != active){
            mRemoteInputActive = active;
            recomputeDisableFlags();
        }
    }

    @Override
    public void onConfigChanged(Configuration newConfig) {
        if (newConfig.orientation != mLastOrientation) {
            misLandscape = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
            mLastOrientation = newConfig.orientation;
            recomputeDisableFlags();
        }
    }

    /**
     * Reapplies the disable flags. Then the method adjustDisableFlags in this class will be invoked
     * in {@link QSFragment#disable(int, int, boolean)} and
     * {@link StatusBar#disable(int, int, boolean)}
     * to modify the disable flags according to the status of mRemoteInputActive and misLandscape.
     */
    private void recomputeDisableFlags() {
        mCommandQueue.recomputeDisableFlags(mContext.getDisplayId(), true);
    }
}
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.systemui.statusbar.policy

import android.app.StatusBarManager
import android.content.Context
import android.content.res.Configuration
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.util.Utils
import javax.inject.Inject

/**
 * Controls whether the disable flag [StatusBarManager.DISABLE2_QUICK_SETTINGS] should be set.
 * This would happen when a [RemoteInputView] is active, the device is in landscape and not using
 * split shade.
 */
@SysUISingleton
class RemoteInputQuickSettingsDisabler @Inject constructor(
    private val context: Context,
    private val commandQueue: CommandQueue,
    configController: ConfigurationController
) : ConfigurationController.ConfigurationListener {

    private var remoteInputActive = false
    private var isLandscape: Boolean
    private var shouldUseSplitNotificationShade: Boolean

    init {
        isLandscape =
            context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
        shouldUseSplitNotificationShade = Utils.shouldUseSplitNotificationShade(context.resources)
        configController.addCallback(this)
    }

    fun adjustDisableFlags(state: Int): Int {
        var mutableState = state
        if (remoteInputActive &&
            isLandscape &&
            !shouldUseSplitNotificationShade
        ) {
            mutableState = state or StatusBarManager.DISABLE2_QUICK_SETTINGS
        }
        return mutableState
    }

    fun setRemoteInputActive(active: Boolean) {
        if (remoteInputActive != active) {
            remoteInputActive = active
            recomputeDisableFlags()
        }
    }

    override fun onConfigChanged(newConfig: Configuration) {
        var needToRecompute = false

        val newIsLandscape = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
        if (newIsLandscape != isLandscape) {
            isLandscape = newIsLandscape
            needToRecompute = true
        }

        val newSplitShadeFlag = Utils.shouldUseSplitNotificationShade(context.resources)
        if (newSplitShadeFlag != shouldUseSplitNotificationShade) {
            shouldUseSplitNotificationShade = newSplitShadeFlag
            needToRecompute = true
        }
        if (needToRecompute) {
            recomputeDisableFlags()
        }
    }

    /**
     * Called in order to trigger a refresh of the disable flags after a relevant configuration
     * change or when a [RemoteInputView] has changed its active state. The method
     * [adjustDisableFlags] will be invoked to modify the disable flags according to
     * [remoteInputActive], [isLandscape] and [shouldUseSplitNotificationShade].
     */
    private fun recomputeDisableFlags() {
        commandQueue.recomputeDisableFlags(context.displayId, true)
    }
}
 No newline at end of file
+2 −2
Original line number Diff line number Diff line
@@ -173,8 +173,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
    protected Fragment instantiate(Context context, String className, Bundle arguments) {
        CommandQueue commandQueue = new CommandQueue(context);
        return new QSFragment(
                new RemoteInputQuickSettingsDisabler(context, mock(ConfigurationController.class),
                        commandQueue),
                new RemoteInputQuickSettingsDisabler(context, commandQueue,
                        mock(ConfigurationController.class)),
                mock(QSTileHost.class),
                mock(StatusBarStateController.class),
                commandQueue,
+0 −95
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package com.android.systemui.statusbar.policy;

import static junit.framework.TestCase.assertTrue;

import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import android.content.res.Configuration;
import android.test.suitebuilder.annotation.SmallTest;

import androidx.test.runner.AndroidJUnit4;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.ConfigurationController;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class RemoteInputQuickSettingsDisablerTest extends SysuiTestCase {

    @Mock
    private CommandQueue mCommandQueue;
    private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mRemoteInputQuickSettingsDisabler = new RemoteInputQuickSettingsDisabler(mContext,
                mock(ConfigurationController.class), mCommandQueue);
    }

    @Test
    public void shouldEnableQuickSetting_afterDeactiviate() {
        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.TRUE);
        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.FALSE);
        assertFalse(mRemoteInputQuickSettingsDisabler.mRemoteInputActive);
        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyInt(), anyBoolean());
    }

    @Test
    public void shouldDisableQuickSetting_afteActiviate() {
        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.FALSE);
        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.TRUE);
        assertTrue(mRemoteInputQuickSettingsDisabler.mRemoteInputActive);
        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyInt(), anyBoolean());
    }

    @Test
    public void testChangeToLandscape() {
        Configuration c = new Configuration(mContext.getResources().getConfiguration());
        c.orientation = Configuration.ORIENTATION_PORTRAIT;
        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
        c.orientation = Configuration.ORIENTATION_LANDSCAPE;
        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
        assertTrue(mRemoteInputQuickSettingsDisabler.misLandscape);
        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyInt(), anyBoolean());
    }

    @Test
    public void testChangeToPortrait() {
        Configuration c = new Configuration(mContext.getResources().getConfiguration());
        c.orientation = Configuration.ORIENTATION_LANDSCAPE;
        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
        c.orientation = Configuration.ORIENTATION_PORTRAIT;
        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
        assertFalse(mRemoteInputQuickSettingsDisabler.misLandscape);
        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyInt(), anyBoolean());
    }

}
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package com.android.systemui.statusbar.policy

import android.app.StatusBarManager
import android.content.res.Configuration
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest

import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.CommandQueue
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations

@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper
class RemoteInputQuickSettingsDisablerTest : SysuiTestCase() {

    @Mock lateinit var commandQueue: CommandQueue
    private lateinit var remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler
    private lateinit var configuration: Configuration

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)

        remoteInputQuickSettingsDisabler = RemoteInputQuickSettingsDisabler(
            mContext,
            commandQueue, Mockito.mock(ConfigurationController::class.java)
        )
        configuration = Configuration(mContext.resources.configuration)

        // Default these conditions to what they need to be to disable QS.
        mContext.orCreateTestableResources
            .addOverride(R.bool.config_use_split_notification_shade, /* value= */false)
        remoteInputQuickSettingsDisabler.setRemoteInputActive(true)
        configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
        remoteInputQuickSettingsDisabler.onConfigChanged(configuration)
    }

    @Test
    fun whenRemoteInputActiveAndLandscapeAndNotSplitShade_shouldDisableQs() {
        assertThat(
            shouldDisableQs(
                remoteInputQuickSettingsDisabler.adjustDisableFlags(0)
            )
        )
            .isTrue()
    }

    @Test
    fun whenRemoteInputNotActive_shouldNotDisableQs() {
        remoteInputQuickSettingsDisabler.setRemoteInputActive(false)

        assertThat(
            shouldDisableQs(
                remoteInputQuickSettingsDisabler.adjustDisableFlags(0)
            )
        )
            .isFalse()
    }

    @Test
    fun whenSplitShadeEnabled_shouldNotDisableQs() {
        mContext.orCreateTestableResources
            .addOverride(R.bool.config_use_split_notification_shade, /* value= */true)
        remoteInputQuickSettingsDisabler.onConfigChanged(configuration)

        assertThat(
            shouldDisableQs(
                remoteInputQuickSettingsDisabler.adjustDisableFlags(0)
            )
        )
            .isFalse()
    }

    @Test
    fun whenPortrait_shouldNotDisableQs() {
        configuration.orientation = Configuration.ORIENTATION_PORTRAIT
        remoteInputQuickSettingsDisabler.onConfigChanged(configuration)

        assertThat(
            shouldDisableQs(
                remoteInputQuickSettingsDisabler.adjustDisableFlags(0)
            )
        )
            .isFalse()
    }

    @Test
    fun whenRemoteInputChanges_recomputeTriggered() {
        remoteInputQuickSettingsDisabler.setRemoteInputActive(false)

        verify(commandQueue, atLeastOnce()).recomputeDisableFlags(
            anyInt(), anyBoolean()
        )
    }

    @Test
    fun whenConfigChanges_recomputeTriggered() {
        configuration.orientation = Configuration.ORIENTATION_PORTRAIT
        remoteInputQuickSettingsDisabler.onConfigChanged(configuration)

        verify(commandQueue, atLeastOnce()).recomputeDisableFlags(
            anyInt(), anyBoolean()
        )
    }

    private fun shouldDisableQs(state: Int): Boolean {
        return state and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0
    }
}
 No newline at end of file