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