• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 package com.android.car.carlauncher;
18 
19 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
20 
21 import static com.android.car.carlauncher.TaskViewManager.DBG;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.app.ActivityManager;
26 import android.content.Context;
27 import android.graphics.Rect;
28 import android.util.Log;
29 import android.util.SparseArray;
30 import android.view.SurfaceControl;
31 import android.window.WindowContainerToken;
32 import android.window.WindowContainerTransaction;
33 
34 import com.android.wm.shell.ShellTaskOrganizer;
35 import com.android.wm.shell.TaskView;
36 import com.android.wm.shell.common.SyncTransactionQueue;
37 
38 /**
39  * CarLauncher version of {@link TaskView} which solves some CarLauncher specific issues:
40  * <ul>
41  * <li>b/228092608: Clears the hidden flag to make it TopFocusedRootTask.</li>
42  * <li>b/225388469: Moves the embedded task to the top to make it resumed.</li>
43  * </ul>
44  */
45 public class CarTaskView extends TaskView {
46     private static final String TAG = CarTaskView.class.getSimpleName();
47     @Nullable
48     private WindowContainerToken mTaskToken;
49     private final SyncTransactionQueue mSyncQueue;
50     private final SparseArray<Rect> mInsets = new SparseArray<>();
51     private boolean mTaskViewReadySent;
52 
CarTaskView(Context context, ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue)53     public CarTaskView(Context context, ShellTaskOrganizer organizer,
54             SyncTransactionQueue syncQueue) {
55         super(context, organizer, /* taskViewTransitions= */ null, syncQueue);
56         mSyncQueue = syncQueue;
57     }
58 
59     @Override
onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash)60     public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
61         mTaskToken = taskInfo.token;
62         super.onTaskAppeared(taskInfo, leash);
63 
64         applyInsets();
65     }
66 
67     @Override
notifyInitialized()68     protected void notifyInitialized() {
69         super.notifyInitialized();
70         if (mTaskViewReadySent) {
71             if (DBG) Log.i(TAG, "car task view ready already sent");
72             return;
73         }
74         onCarTaskViewInitialized();
75         mTaskViewReadySent = true;
76     }
77 
78     /**
79      * Called only once when the {@link CarTaskView} is ready.
80      */
onCarTaskViewInitialized()81     protected void onCarTaskViewInitialized() {}
82 
83     /**
84      * Moves the embedded task over the embedding task to make it shown.
85      */
showEmbeddedTask(WindowContainerTransaction wct)86     public void showEmbeddedTask(WindowContainerTransaction wct) {
87         if (mTaskToken == null) {
88             return;
89         }
90         // Clears the hidden flag to make it TopFocusedRootTask: b/228092608
91         wct.setHidden(mTaskToken, /* hidden= */ false);
92         // Moves the embedded task to the top to make it resumed: b/225388469
93         wct.reorder(mTaskToken, /* onTop= */ true);
94     }
95 
96     // TODO(b/238473897): Consider taking insets one by one instead of taking all insets.
97     /**
98      * Set & apply the given {@code insets} on the Task.
99      *
100      * <p>
101      * The insets that were specified in an earlier call but not specified later, will remain
102      * applied to the task. Clients should explicitly call {@link #removeInsets(int[])} to remove
103      * the insets from the underlying task.
104      * </p>
105      */
setInsets(SparseArray<Rect> insets)106     public void setInsets(SparseArray<Rect> insets) {
107         mInsets.clear();
108         for (int i = insets.size() - 1; i >= 0; i--) {
109             mInsets.append(insets.keyAt(i), insets.valueAt(i));
110         }
111         applyInsets();
112     }
113 
114     /**
115      * Removes the given insets from the Task.
116      *
117      * Note: This will only remove the insets that were set using {@link #setInsets(SparseArray)}
118      *
119      * @param insetsTypes the types of insets to be removed
120      */
removeInsets(@onNull int[] insetsTypes)121     public void removeInsets(@NonNull int[] insetsTypes) {
122         if (mInsets == null || mInsets.size() == 0) {
123             Log.w(TAG, "No insets set.");
124             return;
125         }
126         if (mTaskToken == null) {
127             Log.w(TAG, "Cannot remove insets as the task token is not present.");
128             return;
129         }
130         WindowContainerTransaction wct = new WindowContainerTransaction();
131         for (int i = 0; i < insetsTypes.length; i++) {
132             int insetsType = insetsTypes[i];
133             if (mInsets.indexOfKey(insetsType) != -1) {
134                 wct.removeInsetsProvider(mTaskToken, new int[]{insetsType});
135                 mInsets.remove(insetsType);
136             } else {
137                 Log.w(TAG, "Insets type: " + insetsType + " can't be removed as it was not "
138                         + "applied as part of hte last setInsets()");
139             }
140         }
141         mSyncQueue.queue(wct);
142     }
143 
applyInsets()144     private void applyInsets() {
145         if (mInsets == null || mInsets.size() == 0) {
146             Log.w(TAG, "Cannot apply null or empty insets");
147             return;
148         }
149         if (mTaskToken == null) {
150             Log.w(TAG, "Cannot apply insets as the task token is not present.");
151             return;
152         }
153         WindowContainerTransaction wct = new WindowContainerTransaction();
154         for (int i = 0; i < mInsets.size(); i++) {
155             wct.addRectInsetsProvider(mTaskToken, mInsets.valueAt(i), new int[]{mInsets.keyAt(i)});
156         }
157         mSyncQueue.queue(wct);
158     }
159 
160     /**
161      * @return the taskId of the currently running task.
162      */
getTaskId()163     public int getTaskId() {
164         if (mTaskInfo == null) {
165             return INVALID_TASK_ID;
166         }
167         return mTaskInfo.taskId;
168     }
169 }
170