/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.clipboardoverlay import android.content.ClipData import android.content.ClipDescription.EXTRA_IS_SENSITIVE import android.content.Context import android.graphics.Bitmap import android.net.Uri import android.text.TextUtils import android.util.Log import android.util.Size import android.view.textclassifier.TextLinks import com.android.systemui.res.R import java.io.IOException data class ClipboardModel( val clipData: ClipData, val source: String, val type: Type, val text: CharSequence?, val textLinks: TextLinks?, val uri: Uri?, val isSensitive: Boolean, val isRemote: Boolean, ) { private var _bitmap: Bitmap? = null fun dataMatches(other: ClipboardModel?): Boolean { if (other == null) { return false } return source == other.source && type == other.type && text == other.text && uri == other.uri && isSensitive == other.isSensitive } fun loadThumbnail(context: Context): Bitmap? { if (_bitmap == null && type == Type.IMAGE && uri != null) { try { val size = context.resources.getDimensionPixelSize(R.dimen.overlay_x_scale) _bitmap = context.contentResolver.loadThumbnail(uri, Size(size, size * 4), null) } catch (e: IOException) { Log.e(TAG, "Thumbnail loading failed!", e) } } return _bitmap } internal companion object { private val TAG: String = "ClipboardModel" @JvmStatic fun fromClipData( context: Context, utils: ClipboardOverlayUtils, clipData: ClipData, source: String ): ClipboardModel { val sensitive = clipData.description?.extras?.getBoolean(EXTRA_IS_SENSITIVE) ?: false val item = clipData.getItemAt(0)!! val type = getType(context, item) val remote = utils.isRemoteCopy(context, clipData, source) return ClipboardModel( clipData, source, type, item.text, item.textLinks, item.uri, sensitive, remote ) } private fun getType(context: Context, item: ClipData.Item): Type { return if (!TextUtils.isEmpty(item.text)) { Type.TEXT } else if (item.uri != null) { if (context.contentResolver.getType(item.uri)?.startsWith("image") == true) { Type.IMAGE } else { Type.URI } } else { Type.OTHER } } } enum class Type { TEXT, IMAGE, URI, OTHER } }