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

Commit 102a7307 authored by Uwais Ashraf's avatar Uwais Ashraf
Browse files

Convert ThumbnailData to kotlin for easier mocking in tests

Bug: 334825222
Test: NA - one for one conversion (Presubmit)
Flag: NA
Change-Id: I191860d72efec82fee444297a50710c89aac08a9
parent ec90d944
Loading
Loading
Loading
Loading
+0 −120
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.shared.recents.model;

import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.graphics.Bitmap.Config.ARGB_8888;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.util.Log;
import android.view.WindowInsetsController.Appearance;
import android.window.TaskSnapshot;

import java.util.HashMap;

/**
 * Data for a single thumbnail.
 */
public class ThumbnailData {

    public final Bitmap thumbnail;
    public int orientation;
    public int rotation;
    public Rect insets;
    public Rect letterboxInsets;
    public boolean reducedResolution;
    public boolean isRealSnapshot;
    public boolean isTranslucent;
    public int windowingMode;
    public @Appearance int appearance;
    public float scale;
    public long snapshotId;

    public ThumbnailData() {
        thumbnail = null;
        orientation = ORIENTATION_UNDEFINED;
        rotation = ROTATION_UNDEFINED;
        insets = new Rect();
        letterboxInsets = new Rect();
        reducedResolution = false;
        scale = 1f;
        isRealSnapshot = true;
        isTranslucent = false;
        windowingMode = WINDOWING_MODE_UNDEFINED;
        snapshotId = 0;
    }

    public void recycleBitmap() {
        if (thumbnail != null) {
            thumbnail.recycle();
        }
    }

    private static Bitmap makeThumbnail(TaskSnapshot snapshot) {
        Bitmap thumbnail = null;
        try (final HardwareBuffer buffer = snapshot.getHardwareBuffer()) {
            if (buffer != null) {
                thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.getColorSpace());
            }
        } catch (IllegalArgumentException ex) {
            // TODO(b/157562905): Workaround for a crash when we get a snapshot without this state
            Log.e("ThumbnailData", "Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE: "
                    + snapshot.getHardwareBuffer(), ex);
        }
        if (thumbnail == null) {
            Point taskSize = snapshot.getTaskSize();
            thumbnail = Bitmap.createBitmap(taskSize.x, taskSize.y, ARGB_8888);
            thumbnail.eraseColor(Color.BLACK);
        }
        return thumbnail;
    }

    public static HashMap<Integer, ThumbnailData> wrap(int[] taskIds, TaskSnapshot[] snapshots) {
        HashMap<Integer, ThumbnailData> temp = new HashMap<>();
        if (taskIds == null || snapshots == null || taskIds.length != snapshots.length) {
            return temp;
        }

        for (int i = snapshots.length - 1; i >= 0; i--) {
            temp.put(taskIds[i], new ThumbnailData(snapshots[i]));
        }
        return temp;
    }

    public ThumbnailData(TaskSnapshot snapshot) {
        thumbnail = makeThumbnail(snapshot);
        insets = new Rect(snapshot.getContentInsets());
        letterboxInsets = new Rect(snapshot.getLetterboxInsets());
        orientation = snapshot.getOrientation();
        rotation = snapshot.getRotation();
        reducedResolution = snapshot.isLowResolution();
        // TODO(b/149579527): Pass task size instead of computing scale.
        // Assume width and height were scaled the same; compute scale only for width
        scale = (float) thumbnail.getWidth() / snapshot.getTaskSize().x;
        isRealSnapshot = snapshot.isRealSnapshot();
        isTranslucent = snapshot.isTranslucent();
        windowingMode = snapshot.getWindowingMode();
        appearance = snapshot.getAppearance();
        snapshotId = snapshot.getId();
    }
}
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.shared.recents.model

import android.app.WindowConfiguration
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Bitmap.Config.ARGB_8888
import android.graphics.Color
import android.graphics.Rect
import android.util.Log
import android.view.WindowInsetsController.Appearance
import android.window.TaskSnapshot

/** Data for a single thumbnail. */
data class ThumbnailData(
    val thumbnail: Bitmap? = null,
    var orientation: Int = Configuration.ORIENTATION_UNDEFINED,
    @JvmField var rotation: Int = WindowConfiguration.ROTATION_UNDEFINED,
    @JvmField var insets: Rect = Rect(),
    @JvmField var letterboxInsets: Rect = Rect(),
    @JvmField var reducedResolution: Boolean = false,
    @JvmField var isRealSnapshot: Boolean = true,
    var isTranslucent: Boolean = false,
    @JvmField var windowingMode: Int = WindowConfiguration.WINDOWING_MODE_UNDEFINED,
    @JvmField @Appearance var appearance: Int = 0,
    @JvmField var scale: Float = 1f,
    var snapshotId: Long = 0,
) {
    fun recycleBitmap() {
        thumbnail?.recycle()
    }

    companion object {
        private fun makeThumbnail(snapshot: TaskSnapshot): Bitmap {
            var thumbnail: Bitmap? = null
            try {
                snapshot.hardwareBuffer?.use { buffer ->
                    thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.colorSpace)
                }
            } catch (ex: IllegalArgumentException) {
                // TODO(b/157562905): Workaround for a crash when we get a snapshot without this
                // state
                Log.e(
                    "ThumbnailData",
                    "Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE: " +
                        "${snapshot.hardwareBuffer}",
                    ex
                )
            }

            return thumbnail
                ?: Bitmap.createBitmap(snapshot.taskSize.x, snapshot.taskSize.y, ARGB_8888).apply {
                    eraseColor(Color.BLACK)
                }
        }

        @JvmStatic
        fun wrap(taskIds: IntArray?, snapshots: Array<TaskSnapshot>?): HashMap<Int, ThumbnailData> {
            return if (taskIds == null || snapshots == null || taskIds.size != snapshots.size) {
                HashMap()
            } else {
                HashMap(taskIds.associateWith { taskId -> fromSnapshot(snapshots[taskId]) })
            }
        }

        @JvmStatic
        fun fromSnapshot(snapshot: TaskSnapshot): ThumbnailData {
            val thumbnail = makeThumbnail(snapshot)
            return ThumbnailData(
                thumbnail = thumbnail,
                insets = Rect(snapshot.contentInsets),
                letterboxInsets = Rect(snapshot.letterboxInsets),
                orientation = snapshot.orientation,
                rotation = snapshot.rotation,
                reducedResolution = snapshot.isLowResolution,
                // TODO(b/149579527): Pass task size instead of computing scale.
                // Assume width and height were scaled the same; compute scale only for width
                scale = thumbnail.width.toFloat() / snapshot.taskSize.x,
                isRealSnapshot = snapshot.isRealSnapshot,
                isTranslucent = snapshot.isTranslucent,
                windowingMode = snapshot.windowingMode,
                appearance = snapshot.appearance,
                snapshotId = snapshot.id,
            )
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ public class ActivityManagerWrapper {
            Log.w(TAG, "Failed to retrieve task snapshot", e);
        }
        if (snapshot != null) {
            return new ThumbnailData(snapshot);
            return ThumbnailData.fromSnapshot(snapshot);
        } else {
            return new ThumbnailData();
        }
@@ -167,7 +167,7 @@ public class ActivityManagerWrapper {
            Log.w(TAG, "Failed to take task snapshot", e);
        }
        if (snapshot != null) {
            return new ThumbnailData(snapshot);
            return ThumbnailData.fromSnapshot(snapshot);
        } else {
            return new ThumbnailData();
        }
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ public class RecentsAnimationControllerCompat {
        try {
            final TaskSnapshot snapshot = mAnimationController.screenshotTask(taskId);
            if (snapshot != null) {
                return new ThumbnailData(snapshot);
                return ThumbnailData.fromSnapshot(snapshot);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to screenshot task", e);
+1 −1
Original line number Diff line number Diff line
@@ -351,7 +351,7 @@ public class TaskStackChangeListeners {
                    case ON_TASK_SNAPSHOT_CHANGED: {
                        Trace.beginSection("onTaskSnapshotChanged");
                        final TaskSnapshot snapshot = (TaskSnapshot) msg.obj;
                        final ThumbnailData thumbnail = new ThumbnailData(snapshot);
                        final ThumbnailData thumbnail = ThumbnailData.fromSnapshot(snapshot);
                        boolean snapshotConsumed = false;
                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
                            boolean consumed = mTaskStackListeners.get(i).onTaskSnapshotChanged(
Loading