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

Commit bf2bd0a6 authored by Miranda Kephart's avatar Miranda Kephart
Browse files

Read clipboard item mimetype from description

Currently we construct the clipboard model by calling
contentResolver.getType on the main thread, which can cause problems
because that call can hang.
This change switches to reading the mimeType set in the clip description
instead (which should be set correctly per-item).

Bug: 357197236
Flag: com.android.systemui.clipboard_use_description_mimetype
Test: manual with flag on/off, atest ClipboardModelTest
Change-Id: I78550105f9c4f9b3ee1cf69a732b075397cdf4ac
parent 08d832de
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -581,6 +581,16 @@ flag {
    }
}

flag {
    name: "clipboard_use_description_mimetype"
    namespace: "systemui"
    description: "Read item mimetype from description rather than checking URI"
    bug: "357197236"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "screenshot_action_dismiss_system_windows"
    namespace: "systemui"
+17 −8
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.text.TextUtils
import android.util.Log
import android.util.Size
import android.view.textclassifier.TextLinks
import com.android.systemui.Flags.clipboardUseDescriptionMimetype
import com.android.systemui.res.R
import java.io.IOException

@@ -70,11 +71,11 @@ data class ClipboardModel(
            context: Context,
            utils: ClipboardOverlayUtils,
            clipData: ClipData,
            source: String
            source: String,
        ): ClipboardModel {
            val sensitive = clipData.description?.extras?.getBoolean(EXTRA_IS_SENSITIVE) ?: false
            val item = clipData.getItemAt(0)!!
            val type = getType(context, item)
            val type = getType(context, item, clipData.description.getMimeType(0))
            val remote = utils.isRemoteCopy(context, clipData, source)
            return ClipboardModel(
                clipData,
@@ -84,19 +85,27 @@ data class ClipboardModel(
                item.textLinks,
                item.uri,
                sensitive,
                remote
                remote,
            )
        }

        private fun getType(context: Context, item: ClipData.Item): Type {
        private fun getType(context: Context, item: ClipData.Item, mimeType: String): Type {
            return if (!TextUtils.isEmpty(item.text)) {
                Type.TEXT
            } else if (item.uri != null) {
                if (clipboardUseDescriptionMimetype()) {
                    if (mimeType.startsWith("image")) {
                        Type.IMAGE
                    } else {
                        Type.URI
                    }
                } else {
                    if (context.contentResolver.getType(item.uri)?.startsWith("image") == true) {
                        Type.IMAGE
                    } else {
                        Type.URI
                    }
                }
            } else {
                Type.OTHER
            }
@@ -107,6 +116,6 @@ data class ClipboardModel(
        TEXT,
        IMAGE,
        URI,
        OTHER
        OTHER,
    }
}
+21 −2
Original line number Diff line number Diff line
@@ -22,10 +22,12 @@ import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.os.PersistableBundle
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_USE_DESCRIPTION_MIMETYPE
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.whenever
import java.io.IOException
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -37,6 +39,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.whenever

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -88,7 +91,8 @@ class ClipboardModelTest : SysuiTestCase() {

    @Test
    @Throws(IOException::class)
    fun test_imageClipData() {
    @DisableFlags(FLAG_CLIPBOARD_USE_DESCRIPTION_MIMETYPE)
    fun test_imageClipData_legacy() {
        val testBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888)
        whenever(mMockContext.contentResolver).thenReturn(mMockContentResolver)
        whenever(mMockContext.resources).thenReturn(mContext.resources)
@@ -101,6 +105,21 @@ class ClipboardModelTest : SysuiTestCase() {
        assertEquals(testBitmap, model.loadThumbnail(mMockContext))
    }

    @Test
    @Throws(IOException::class)
    @EnableFlags(FLAG_CLIPBOARD_USE_DESCRIPTION_MIMETYPE)
    fun test_imageClipData() {
        val testBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888)
        whenever(mMockContext.contentResolver).thenReturn(mMockContentResolver)
        whenever(mMockContext.resources).thenReturn(mContext.resources)
        whenever(mMockContentResolver.loadThumbnail(any(), any(), any())).thenReturn(testBitmap)
        whenever(mMockContentResolver.getType(any())).thenReturn("text")
        val imageClipData = ClipData("Test", arrayOf("image/png"), ClipData.Item(Uri.parse("test")))
        val model = ClipboardModel.fromClipData(mMockContext, mClipboardUtils, imageClipData, "")
        assertEquals(ClipboardModel.Type.IMAGE, model.type)
        assertEquals(testBitmap, model.loadThumbnail(mMockContext))
    }

    @Test
    @Throws(IOException::class)
    fun test_imageClipData_loadFailure() {