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

Commit 123a85fd authored by Beth Thibodeau's avatar Beth Thibodeau
Browse files

[DO NOT MERGE] Move code to fix studio build

Move actual implementation here because it was causing studio build to
fail. The device-specific values are already overlaid where necessary to
enable/disable the info panel from showing up

Bug: 183032541
Test: manual
Test: atest GlobalActionsInfoProviderTest
Change-Id: I3ea09c99f1d949488f28b71875fdd8bdadb93c7a
parent 81858ab4
Loading
Loading
Loading
Loading
+81 −3
Original line number Diff line number Diff line
@@ -15,14 +15,32 @@
 */
package com.android.systemui.globalactions

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
import android.service.quickaccesswallet.QuickAccessWalletClient
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
import com.android.systemui.R
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.plugins.ActivityStarter
import javax.inject.Inject

// Empty class, will be overridden for relevant devices
private const val TAG = "GlobalActionsInfo"

/** Maximum number of times to show change info message  */
private const val MAX_VIEW_COUNT = 3

/** Maximum number of buttons allowed in landscape before this panel does not fit */
private const val MAX_BUTTONS_LANDSCAPE = 4

private const val PREFERENCE = "global_actions_info_prefs"
private const val KEY_VIEW_COUNT = "view_count"

class GlobalActionsInfoProvider @Inject constructor(
    private val context: Context,
    private val walletClient: QuickAccessWalletClient,
@@ -30,9 +48,69 @@ class GlobalActionsInfoProvider @Inject constructor(
    private val activityStarter: ActivityStarter
) {

    fun addPanel(context: Context, parent: ViewGroup, nActions: Int, dismissParent: Runnable) { }
    private var pendingIntent: PendingIntent

    init {
        val url = context.resources.getString(R.string.global_actions_change_url)
        val intent = Intent(Intent.ACTION_VIEW).apply {
            setData(Uri.parse(url))
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
    }

    fun addPanel(context: Context, parent: ViewGroup, nActions: Int, dismissParent: Runnable) {
        // This panel does not fit on landscape with two rows of buttons showing,
        // so skip adding the panel (and incrementing view counT) in that case
        val isLandscape =
                context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
        if (isLandscape && nActions > MAX_BUTTONS_LANDSCAPE) {
            return
        }

        val view = LayoutInflater.from(context).inflate(R.layout.global_actions_change_panel,
                parent, false)
        val button = view.findViewById<ImageView>(R.id.global_actions_change_button)
        button.setOnClickListener { _ ->
            dismissParent.run()
            activityStarter.postStartActivityDismissingKeyguard(pendingIntent)
        }
        parent.addView(view, 0) // Add to top
        incrementViewCount()
    }

    fun shouldShowMessage(): Boolean {
        // This is only relevant for some devices
        val isEligible = context.resources.getBoolean(
                R.bool.global_actions_show_change_info)
        if (!isEligible) {
            return false
        }

        val sharedPrefs = context.getSharedPreferences(PREFERENCE, Context.MODE_PRIVATE)

        // Only show to users who previously had these items set up
        val viewCount = if (sharedPrefs.contains(KEY_VIEW_COUNT) || hadContent()) {
            sharedPrefs.getInt(KEY_VIEW_COUNT, 0)
        } else {
            -1
        }

        // Limit number of times this is displayed
        return viewCount > -1 && viewCount < MAX_VIEW_COUNT
    }

    private fun hadContent(): Boolean {
        // Check whether user would have seen content in the power menu that has now moved
        val hadControls = controlsController.getFavorites().size > 0
        val hadCards = walletClient.isWalletFeatureAvailable
        Log.d(TAG, "Previously had controls $hadControls, cards $hadCards")
        return hadControls || hadCards
    }

    private fun incrementViewCount() {
        val sharedPrefs = context.getSharedPreferences(PREFERENCE, Context.MODE_PRIVATE)
        val count = sharedPrefs.getInt(KEY_VIEW_COUNT, 0)
        sharedPrefs.edit().putInt(KEY_VIEW_COUNT, count + 1).apply()
    }
}
 No newline at end of file
+76 −15
Original line number Diff line number Diff line
@@ -14,45 +14,75 @@
 * limitations under the License.
 */

package com.android.systemui.globalactions
package com.google.android.systemui.globalactions

import android.content.Context
import android.content.SharedPreferences
import android.content.res.Configuration
import android.content.res.Resources
import android.service.quickaccesswallet.QuickAccessWalletClient
import android.testing.AndroidTestingRunner
import android.view.ViewGroup
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.R
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.globalactions.GlobalActionsInfoProvider
import com.android.systemui.plugins.ActivityStarter
import com.google.common.truth.Truth.assertThat
import com.android.systemui.SysuiTestCase
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
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.ArgumentMatchers.anyObject
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever

private const val PREFERENCE = "global_actions_info_prefs"
private const val KEY_VIEW_COUNT = "view_count"

private fun <T> eq(value: T): T = Mockito.eq(value) ?: value

@SmallTest
@RunWith(AndroidTestingRunner::class)
class GlobalActionsInfoProviderTest : SysuiTestCase() {

    @Mock
    private lateinit var walletClient: QuickAccessWalletClient
    @Mock
    private lateinit var controlsController: ControlsController
    @Mock
    private lateinit var activityStarter: ActivityStarter
    @Mock private lateinit var walletClient: QuickAccessWalletClient
    @Mock private lateinit var controlsController: ControlsController
    @Mock private lateinit var activityStarter: ActivityStarter
    @Mock private lateinit var mockContext: Context
    @Mock private lateinit var mockResources: Resources
    @Mock private lateinit var sharedPrefs: SharedPreferences
    @Mock private lateinit var sharedPrefsEditor: SharedPreferences.Editor

    private lateinit var infoProvider: GlobalActionsInfoProvider

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        mockContext = spy(context)
        mockResources = spy(context.resources)
        whenever(mockContext.resources).thenReturn(mockResources)
        whenever(mockResources.getBoolean(R.bool.global_actions_show_change_info))
                .thenReturn(true)
        whenever(mockContext.getSharedPreferences(eq(PREFERENCE), anyInt()))
                .thenReturn(sharedPrefs)
        whenever(sharedPrefs.edit()).thenReturn(sharedPrefsEditor)
        whenever(sharedPrefsEditor.putInt(anyString(), anyInt())).thenReturn(sharedPrefsEditor)
        whenever(sharedPrefsEditor.putBoolean(anyString(), anyBoolean()))
                .thenReturn(sharedPrefsEditor)

        infoProvider = GlobalActionsInfoProvider(
                context,
                mockContext,
                walletClient,
                controlsController,
                activityStarter
@@ -60,14 +90,45 @@ class GlobalActionsInfoProviderTest : SysuiTestCase() {
    }

    @Test
    fun testAddPanel_doesNothing() {
    fun testIsEligible_noCards() {
        whenever(sharedPrefs.contains(eq(KEY_VIEW_COUNT))).thenReturn(false)
        whenever(walletClient.isWalletFeatureAvailable).thenReturn(false)

        assertFalse(infoProvider.shouldShowMessage())
    }

    @Test
    fun testIsEligible_hasCards() {
        whenever(sharedPrefs.contains(eq(KEY_VIEW_COUNT))).thenReturn(false)
        whenever(walletClient.isWalletFeatureAvailable).thenReturn(true)

        assertTrue(infoProvider.shouldShowMessage())
    }

    @Test
    fun testNotEligible_shouldNotShow() {
        whenever(mockResources.getBoolean(R.bool.global_actions_show_change_info))
                .thenReturn(false)

        assertFalse(infoProvider.shouldShowMessage())
    }

    @Test
    fun testTooManyButtons_doesNotAdd() {
        val configuration = Configuration()
        configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
        whenever(mockResources.configuration).thenReturn(configuration)

        val parent = mock(ViewGroup::class.java)
        infoProvider.addPanel(context, parent, 1, { })
        infoProvider.addPanel(mockContext, parent, 5, { })

        verify(parent, never()).addView(anyObject(), anyInt())
    }

    @Test
    fun testShouldShowPanel() {
        assertThat(infoProvider.shouldShowMessage()).isFalse()
    fun testLimitTimesShown() {
        whenever(sharedPrefs.getInt(eq(KEY_VIEW_COUNT), anyInt())).thenReturn(4)

        assertFalse(infoProvider.shouldShowMessage())
    }
}
 No newline at end of file