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

Commit 3c59d9b3 authored by Ats Jenk's avatar Ats Jenk
Browse files

Desktop tile that is a snapshot of desktop

Create a desktop recents tile that shows a snapshot of the freeform
tasks running on desktop.
Scales them down and positions them in the same location as they would
be on the desktop.

Bug: 244348395
Test: manual
Change-Id: Ieb5830a331691844769003189f557c4b7e4cd35c
parent 1874371a
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2022 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.
-->

<com.android.quickstep.views.DesktopTaskView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="true"
    android:clipToOutline="true"
    android:defaultFocusHighlightEnabled="false"
    android:focusable="true">

    <!--
         TODO(b249371338): DesktopTaskView extends from TaskView. TaskView expects TaskThumbnailView
         and IconView with these ids to be present. Need to refactor RecentsView to accept child
         views that do not inherint from TaskView only or create a generic TaskView that have
         N number of tasks.
     -->
    <com.android.quickstep.views.TaskThumbnailView
        android:id="@+id/snapshot"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <com.android.quickstep.views.IconView
        android:id="@+id/icon"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:focusable="false"
        android:importantForAccessibility="no"
        android:visibility="gone" />

</com.android.quickstep.views.DesktopTaskView>
+1 −0
Original line number Diff line number Diff line
@@ -1829,6 +1829,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
    }

    private void finishCurrentTransitionToRecents() {
        // TODO(b/245569277#comment2): enable once isFreeformActive is implemented
        mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
        if (mRecentsAnimationController != null) {
            mRecentsAnimationController.detachNavigationBarFromApp(true);
+18 −10
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.quickstep;

import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED;
import static com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_FREEFORM;

import android.annotation.TargetApi;
import android.app.ActivityManager;
@@ -30,6 +32,7 @@ import androidx.annotation.VisibleForTesting;

import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
import com.android.systemui.shared.recents.model.Task;
import com.android.wm.shell.recents.IRecentTasksListener;
@@ -253,8 +256,9 @@ public class RecentTasksList {
        };

        TaskLoadResult allTasks = new TaskLoadResult(requestId, loadKeysOnly, rawTasks.size());

        for (GroupedRecentTaskInfo rawTask : rawTasks) {
            if (rawTask.getType() == GroupedRecentTaskInfo.TYPE_FREEFORM) {
            if (DESKTOP_MODE_SUPPORTED && rawTask.getType() == TYPE_FREEFORM) {
                GroupTask desktopTask = createDesktopTask(rawTask);
                allTasks.add(desktopTask);
                continue;
@@ -284,14 +288,18 @@ public class RecentTasksList {
        return allTasks;
    }

    private GroupTask createDesktopTask(GroupedRecentTaskInfo taskInfo) {
        // TODO(b/244348395): create a subclass of GroupTask for desktop tile
        // We need a single task information as the primary task. Use the first task
        Task.TaskKey key = new Task.TaskKey(taskInfo.getTaskInfo1());
        Task task = new Task(key);
        task.desktopTile = true;
        task.topActivity = key.sourceComponent;
        return new GroupTask(task, null, null);
    private DesktopTask createDesktopTask(GroupedRecentTaskInfo recentTaskInfo) {
        ArrayList<Task> tasks = new ArrayList<>(recentTaskInfo.getTaskInfoList().size());
        for (ActivityManager.RecentTaskInfo taskInfo : recentTaskInfo.getTaskInfoList()) {
            Task.TaskKey key = new Task.TaskKey(taskInfo);
            Task task = Task.from(key, taskInfo, false);
            task.setLastSnapshotData(taskInfo);
            task.positionInParent = taskInfo.positionInParent;
            task.appBounds = taskInfo.configuration.windowConfiguration.getAppBounds();
            // TODO(b/244348395): tasks should be sorted from oldest to most recently used
            tasks.add(task);
        }
        return new DesktopTask(tasks);
    }

    private SplitConfigurationOptions.SplitBounds convertSplitBounds(
@@ -306,7 +314,7 @@ public class RecentTasksList {
    private ArrayList<GroupTask> copyOf(ArrayList<GroupTask> tasks) {
        ArrayList<GroupTask> newTasks = new ArrayList<>();
        for (int i = 0; i < tasks.size(); i++) {
            newTasks.add(new GroupTask(tasks.get(i)));
            newTasks.add(tasks.get(i).copy());
        }
        return newTasks;
    }
+12 −6
Original line number Diff line number Diff line
@@ -302,9 +302,15 @@ public final class TaskViewUtils {
            // to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is:
            //    Mt K(0)` K(t) Mt`
            TaskThumbnailView[] thumbnails = v.getThumbnails();
            Matrix[] mt = new Matrix[simulatorCopies.length];
            Matrix[] mti = new Matrix[simulatorCopies.length];
            for (int i = 0; i < thumbnails.length; i++) {

            // In case simulator copies and thumbnail size do no match, ensure we get the lesser.
            // This ensures we do not create arrays with empty elements or attempt to references
            // indexes out of array bounds.
            final int matrixSize = Math.min(simulatorCopies.length, thumbnails.length);

            Matrix[] mt = new Matrix[matrixSize];
            Matrix[] mti = new Matrix[matrixSize];
            for (int i = 0; i < matrixSize; i++) {
                TaskThumbnailView ttv = thumbnails[i];
                RectF localBounds = new RectF(0, 0,  ttv.getWidth(), ttv.getHeight());
                float[] tvBoundsMapped = new float[]{0, 0,  ttv.getWidth(), ttv.getHeight()};
@@ -321,14 +327,14 @@ public final class TaskViewUtils {
                mti[i] = localMti;
            }

            Matrix[] k0i = new Matrix[simulatorCopies.length];
            for (int i = 0; i < simulatorCopies.length; i++) {
            Matrix[] k0i = new Matrix[matrixSize];
            for (int i = 0; i < matrixSize; i++) {
                k0i[i] = new Matrix();
                simulatorCopies[i].getTaskViewSimulator().getCurrentMatrix().invert(k0i[i]);
            }
            Matrix animationMatrix = new Matrix();
            out.addOnFrameCallback(() -> {
                for (int i = 0; i < simulatorCopies.length; i++) {
                for (int i = 0; i < matrixSize; i++) {
                    animationMatrix.set(mt[i]);
                    animationMatrix.postConcat(k0i[i]);
                    animationMatrix.postConcat(simulatorCopies[i]
+56 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.quickstep.util;

import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;

import java.util.ArrayList;

/**
 * A {@link Task} container that can contain N number of tasks that are part of the desktop in
 * recent tasks list.
 */
public class DesktopTask extends GroupTask {

    public ArrayList<Task> tasks;

    public DesktopTask(ArrayList<Task> tasks) {
        super(tasks.get(0), null, null, TaskView.Type.DESKTOP);
        this.tasks = tasks;
    }

    @Override
    public boolean containsTask(int taskId) {
        for (Task task : tasks) {
            if (task.key.id == taskId) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean hasMultipleTasks() {
        return true;
    }

    @Override
    public DesktopTask copy() {
        return new DesktopTask(tasks);
    }
}
Loading