1 /* <lambda>null2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.systemui.shared.recents.model 17 18 import android.app.WindowConfiguration 19 import android.content.res.Configuration 20 import android.graphics.Bitmap 21 import android.graphics.Bitmap.Config.ARGB_8888 22 import android.graphics.Color 23 import android.graphics.Rect 24 import android.util.Log 25 import android.view.WindowInsetsController.Appearance 26 import android.window.TaskSnapshot 27 28 /** Data for a single thumbnail. */ 29 data class ThumbnailData( 30 val thumbnail: Bitmap? = null, 31 var orientation: Int = Configuration.ORIENTATION_UNDEFINED, 32 @JvmField var rotation: Int = WindowConfiguration.ROTATION_UNDEFINED, 33 @JvmField var insets: Rect = Rect(), 34 @JvmField var letterboxInsets: Rect = Rect(), 35 @JvmField var reducedResolution: Boolean = false, 36 @JvmField var isRealSnapshot: Boolean = true, 37 var isTranslucent: Boolean = false, 38 @JvmField var windowingMode: Int = WindowConfiguration.WINDOWING_MODE_UNDEFINED, 39 @JvmField @Appearance var appearance: Int = 0, 40 @JvmField var scale: Float = 1f, 41 var snapshotId: Long = 0, 42 ) { 43 fun recycleBitmap() { 44 thumbnail?.recycle() 45 } 46 47 companion object { 48 private fun makeThumbnail(snapshot: TaskSnapshot): Bitmap { 49 var thumbnail: Bitmap? = null 50 try { 51 snapshot.hardwareBuffer?.use { buffer -> 52 thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.colorSpace) 53 } 54 } catch (ex: IllegalArgumentException) { 55 // TODO(b/157562905): Workaround for a crash when we get a snapshot without this 56 // state 57 Log.e( 58 "ThumbnailData", 59 "Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE: " + 60 "${snapshot.hardwareBuffer}", 61 ex 62 ) 63 } 64 65 return thumbnail 66 ?: Bitmap.createBitmap(snapshot.taskSize.x, snapshot.taskSize.y, ARGB_8888).apply { 67 eraseColor(Color.BLACK) 68 } 69 } 70 71 @JvmStatic 72 fun wrap(taskIds: IntArray?, snapshots: Array<TaskSnapshot>?): HashMap<Int, ThumbnailData> { 73 return hashMapOf<Int, ThumbnailData>().apply { 74 if (taskIds != null && snapshots != null && taskIds.size == snapshots.size) { 75 repeat(snapshots.size) { put(taskIds[it], fromSnapshot(snapshots[it])) } 76 } 77 } 78 } 79 80 @JvmStatic 81 fun fromSnapshot(snapshot: TaskSnapshot): ThumbnailData { 82 val thumbnail = makeThumbnail(snapshot) 83 return ThumbnailData( 84 thumbnail = thumbnail, 85 insets = Rect(snapshot.contentInsets), 86 letterboxInsets = Rect(snapshot.letterboxInsets), 87 orientation = snapshot.orientation, 88 rotation = snapshot.rotation, 89 reducedResolution = snapshot.isLowResolution, 90 // TODO(b/149579527): Pass task size instead of computing scale. 91 // Assume width and height were scaled the same; compute scale only for width 92 scale = thumbnail.width.toFloat() / snapshot.taskSize.x, 93 isRealSnapshot = snapshot.isRealSnapshot, 94 isTranslucent = snapshot.isTranslucent, 95 windowingMode = snapshot.windowingMode, 96 appearance = snapshot.appearance, 97 snapshotId = snapshot.id, 98 ) 99 } 100 } 101 } 102