Merge "[DO NOT MERGE] Move code to fix studio build" into sc-dev
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt
index ee7f5ed..39008ee 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsInfoProvider.kt
@@ -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 @@
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 {
- return false
+ // 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
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsInfoProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsInfoProviderTest.kt
index d3b9228..302a8d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsInfoProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsInfoProviderTest.kt
@@ -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 @@
}
@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