Merge "[DO NOT MERGE] Move code to fix studio build" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e77df8f538
@@ -15,14 +15,32 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.systemui.globalactions
|
package com.android.systemui.globalactions
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.net.Uri
|
||||||
import android.service.quickaccesswallet.QuickAccessWalletClient
|
import android.service.quickaccesswallet.QuickAccessWalletClient
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import com.android.systemui.R
|
||||||
import com.android.systemui.controls.controller.ControlsController
|
import com.android.systemui.controls.controller.ControlsController
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import javax.inject.Inject
|
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(
|
class GlobalActionsInfoProvider @Inject constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val walletClient: QuickAccessWalletClient,
|
private val walletClient: QuickAccessWalletClient,
|
||||||
@@ -30,9 +48,69 @@ class GlobalActionsInfoProvider @Inject constructor(
|
|||||||
private val activityStarter: ActivityStarter
|
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 {
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,45 +14,75 @@
|
|||||||
* limitations under the License.
|
* 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.service.quickaccesswallet.QuickAccessWalletClient
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.test.filters.SmallTest
|
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.controls.controller.ControlsController
|
||||||
|
import com.android.systemui.globalactions.GlobalActionsInfoProvider
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
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.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentMatchers.anyBoolean
|
||||||
import org.mockito.ArgumentMatchers.anyInt
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
import org.mockito.ArgumentMatchers.anyObject
|
import org.mockito.ArgumentMatchers.anyObject
|
||||||
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
import org.mockito.Mockito.verify
|
|
||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
|
import org.mockito.Mockito.spy
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.MockitoAnnotations
|
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
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
class GlobalActionsInfoProviderTest : SysuiTestCase() {
|
class GlobalActionsInfoProviderTest : SysuiTestCase() {
|
||||||
|
|
||||||
@Mock
|
@Mock private lateinit var walletClient: QuickAccessWalletClient
|
||||||
private lateinit var walletClient: QuickAccessWalletClient
|
@Mock private lateinit var controlsController: ControlsController
|
||||||
@Mock
|
@Mock private lateinit var activityStarter: ActivityStarter
|
||||||
private lateinit var controlsController: ControlsController
|
@Mock private lateinit var mockContext: Context
|
||||||
@Mock
|
@Mock private lateinit var mockResources: Resources
|
||||||
private lateinit var activityStarter: ActivityStarter
|
@Mock private lateinit var sharedPrefs: SharedPreferences
|
||||||
|
@Mock private lateinit var sharedPrefsEditor: SharedPreferences.Editor
|
||||||
|
|
||||||
private lateinit var infoProvider: GlobalActionsInfoProvider
|
private lateinit var infoProvider: GlobalActionsInfoProvider
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
MockitoAnnotations.initMocks(this)
|
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(
|
infoProvider = GlobalActionsInfoProvider(
|
||||||
context,
|
mockContext,
|
||||||
walletClient,
|
walletClient,
|
||||||
controlsController,
|
controlsController,
|
||||||
activityStarter
|
activityStarter
|
||||||
@@ -60,14 +90,45 @@ class GlobalActionsInfoProviderTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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)
|
val parent = mock(ViewGroup::class.java)
|
||||||
infoProvider.addPanel(context, parent, 1, { })
|
infoProvider.addPanel(mockContext, parent, 5, { })
|
||||||
|
|
||||||
verify(parent, never()).addView(anyObject(), anyInt())
|
verify(parent, never()).addView(anyObject(), anyInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testShouldShowPanel() {
|
fun testLimitTimesShown() {
|
||||||
assertThat(infoProvider.shouldShowMessage()).isFalse()
|
whenever(sharedPrefs.getInt(eq(KEY_VIEW_COUNT), anyInt())).thenReturn(4)
|
||||||
|
|
||||||
|
assertFalse(infoProvider.shouldShowMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user