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

Commit 65105a24 authored by Miranda Kephart's avatar Miranda Kephart
Browse files

Fix image loading in clipboard UI for secondary user

Bug: 217922018
Test: manual via adding a secondary user, verified via logs
Flag: com.android.systemui.clipboard_overlay_multiuser
Change-Id: Idffb937ddb6e9ddae0e0f6e061a1d249ef5628ac
parent 87e94275
Loading
Loading
Loading
Loading
+57 −8
Original line number Diff line number Diff line
@@ -17,14 +17,17 @@ package com.android.systemui.clipboardoverlay

import android.content.ContentResolver
import android.content.Context
import android.content.pm.UserInfo
import android.net.Uri
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_CLIPBOARD_OVERLAY_MULTIUSER
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.whenever
import com.android.systemui.settings.FakeUserTracker
import java.io.IOException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertNull
@@ -36,44 +39,90 @@ import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.whenever

@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
class ClipboardImageLoaderTest : SysuiTestCase() {
    @Mock private lateinit var mockContext: Context

    @Mock private lateinit var mockContentResolver: ContentResolver
    @Mock private lateinit var mockSecondaryContentResolver: ContentResolver

    private lateinit var clipboardImageLoader: ClipboardImageLoader
    private var fakeUserTracker: FakeUserTracker =
        FakeUserTracker(userContentResolverProvider = { mockContentResolver })

    private val userInfos = listOf(UserInfo(0, "system", 0), UserInfo(50, "secondary", 0))

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

        fakeUserTracker.set(userInfos, 0)
    }

    @Test
    @Throws(IOException::class)
    @DisableFlags(FLAG_CLIPBOARD_OVERLAY_MULTIUSER)
    fun test_imageLoadSuccess_legacy() = runTest {
        val testDispatcher = StandardTestDispatcher(this.testScheduler)
        fakeUserTracker =
            FakeUserTracker(userContentResolverProvider = { mockSecondaryContentResolver })
        fakeUserTracker.set(userInfos, 1)

        clipboardImageLoader =
            ClipboardImageLoader(
                mockContext,
                fakeUserTracker,
                testDispatcher,
                CoroutineScope(testDispatcher),
            )
        val testUri = Uri.parse("testUri")
        whenever<ContentResolver?>(mockContext.contentResolver)
            .thenReturn(mockSecondaryContentResolver)
        whenever(mockContext.resources).thenReturn(context.resources)

        clipboardImageLoader.load(testUri)

        verify(mockSecondaryContentResolver).loadThumbnail(eq(testUri), any(), any())
    }

    @Test
    @Throws(IOException::class)
    @EnableFlags(FLAG_CLIPBOARD_OVERLAY_MULTIUSER)
    fun test_imageLoadSuccess() = runTest {
        val testDispatcher = StandardTestDispatcher(this.testScheduler)
        fakeUserTracker =
            FakeUserTracker(userContentResolverProvider = { mockSecondaryContentResolver })
        fakeUserTracker.set(userInfos, 1)

        clipboardImageLoader =
            ClipboardImageLoader(mockContext, testDispatcher, CoroutineScope(testDispatcher))
            ClipboardImageLoader(
                mockContext,
                fakeUserTracker,
                testDispatcher,
                CoroutineScope(testDispatcher),
            )
        val testUri = Uri.parse("testUri")
        whenever(mockContext.contentResolver).thenReturn(mockContentResolver)
        whenever(mockContext.resources).thenReturn(context.resources)

        clipboardImageLoader.load(testUri)

        verify(mockContentResolver).loadThumbnail(eq(testUri), any(), any())
        verify(mockSecondaryContentResolver).loadThumbnail(eq(testUri), any(), any())
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    @Throws(IOException::class)
    fun test_imageLoadFailure() = runTest {
        val testDispatcher = StandardTestDispatcher(this.testScheduler)
        clipboardImageLoader =
            ClipboardImageLoader(mockContext, testDispatcher, CoroutineScope(testDispatcher))
            ClipboardImageLoader(
                mockContext,
                fakeUserTracker,
                testDispatcher,
                CoroutineScope(testDispatcher),
            )
        val testUri = Uri.parse("testUri")
        whenever(mockContext.contentResolver).thenReturn(mockContentResolver)
        whenever(mockContext.resources).thenReturn(context.resources)
+15 −4
Original line number Diff line number Diff line
@@ -20,15 +20,17 @@ import android.graphics.Bitmap
import android.net.Uri
import android.util.Log
import android.util.Size
import com.android.systemui.res.R
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.Flags.clipboardOverlayMultiuser
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import java.io.IOException
import java.util.function.Consumer
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull

@@ -36,8 +38,9 @@ class ClipboardImageLoader
@Inject
constructor(
    private val context: Context,
    private val userTracker: UserTracker,
    @Background private val bgDispatcher: CoroutineDispatcher,
    @Application private val mainScope: CoroutineScope
    @Application private val mainScope: CoroutineScope,
) {
    private val TAG: String = "ClipboardImageLoader"

@@ -46,7 +49,15 @@ constructor(
            withContext(bgDispatcher) {
                try {
                    val size = context.resources.getDimensionPixelSize(R.dimen.overlay_x_scale)
                    if (clipboardOverlayMultiuser()) {
                        userTracker.userContentResolver.loadThumbnail(
                            uri,
                            Size(size, size * 4),
                            null,
                        )
                    } else {
                        context.contentResolver.loadThumbnail(uri, Size(size, size * 4), null)
                    }
                } catch (e: IOException) {
                    Log.e(TAG, "Thumbnail loading failed!", e)
                    null