1 /* 2 * Copyright (C) 2014 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.systemui.shared.recents.model; 18 19 import android.app.ActivityManager.TaskDescription; 20 import android.content.ComponentName; 21 import android.content.Intent; 22 import android.content.pm.ActivityInfo; 23 import android.graphics.Color; 24 import android.graphics.drawable.Drawable; 25 import android.view.ViewDebug; 26 27 import com.android.systemui.shared.recents.utilities.Utilities; 28 29 import java.io.PrintWriter; 30 import java.util.ArrayList; 31 import java.util.Objects; 32 33 /** 34 * A task represents the top most task in the system's task stack. 35 */ 36 public class Task { 37 38 public static final String TAG = "Task"; 39 40 /* Task callbacks */ 41 public interface TaskCallbacks { 42 /* Notifies when a task has been bound */ onTaskDataLoaded(Task task, ThumbnailData thumbnailData)43 void onTaskDataLoaded(Task task, ThumbnailData thumbnailData); 44 /* Notifies when a task has been unbound */ onTaskDataUnloaded()45 void onTaskDataUnloaded(); 46 /* Notifies when a task's windowing mode has changed. */ onTaskWindowingModeChanged()47 void onTaskWindowingModeChanged(); 48 } 49 50 /* The Task Key represents the unique primary key for the task */ 51 public static class TaskKey { 52 @ViewDebug.ExportedProperty(category="recents") 53 public final int id; 54 @ViewDebug.ExportedProperty(category="recents") 55 public int windowingMode; 56 @ViewDebug.ExportedProperty(category="recents") 57 public final Intent baseIntent; 58 @ViewDebug.ExportedProperty(category="recents") 59 public final int userId; 60 @ViewDebug.ExportedProperty(category="recents") 61 public long lastActiveTime; 62 63 // The source component name which started this task 64 public final ComponentName sourceComponent; 65 66 private int mHashCode; 67 TaskKey(int id, int windowingMode, Intent intent, ComponentName sourceComponent, int userId, long lastActiveTime)68 public TaskKey(int id, int windowingMode, Intent intent, 69 ComponentName sourceComponent, int userId, long lastActiveTime) { 70 this.id = id; 71 this.windowingMode = windowingMode; 72 this.baseIntent = intent; 73 this.sourceComponent = sourceComponent; 74 this.userId = userId; 75 this.lastActiveTime = lastActiveTime; 76 updateHashCode(); 77 } 78 setWindowingMode(int windowingMode)79 public void setWindowingMode(int windowingMode) { 80 this.windowingMode = windowingMode; 81 updateHashCode(); 82 } 83 getComponent()84 public ComponentName getComponent() { 85 return this.baseIntent.getComponent(); 86 } 87 getPackageName()88 public String getPackageName() { 89 if (this.baseIntent.getComponent() != null) { 90 return this.baseIntent.getComponent().getPackageName(); 91 } 92 return this.baseIntent.getPackage(); 93 } 94 95 @Override equals(Object o)96 public boolean equals(Object o) { 97 if (!(o instanceof TaskKey)) { 98 return false; 99 } 100 TaskKey otherKey = (TaskKey) o; 101 return id == otherKey.id 102 && windowingMode == otherKey.windowingMode 103 && userId == otherKey.userId; 104 } 105 106 @Override hashCode()107 public int hashCode() { 108 return mHashCode; 109 } 110 111 @Override toString()112 public String toString() { 113 return "id=" + id + " windowingMode=" + windowingMode + " user=" + userId 114 + " lastActiveTime=" + lastActiveTime; 115 } 116 updateHashCode()117 private void updateHashCode() { 118 mHashCode = Objects.hash(id, windowingMode, userId); 119 } 120 } 121 122 @ViewDebug.ExportedProperty(deepExport=true, prefix="key_") 123 public TaskKey key; 124 125 /** 126 * The temporary sort index in the stack, used when ordering the stack. 127 */ 128 public int temporarySortIndexInStack; 129 130 /** 131 * The icon is the task description icon (if provided), which falls back to the activity icon, 132 * which can then fall back to the application icon. 133 */ 134 public Drawable icon; 135 public ThumbnailData thumbnail; 136 @ViewDebug.ExportedProperty(category="recents") 137 public String title; 138 @ViewDebug.ExportedProperty(category="recents") 139 public String titleDescription; 140 @ViewDebug.ExportedProperty(category="recents") 141 public int colorPrimary; 142 @ViewDebug.ExportedProperty(category="recents") 143 public int colorBackground; 144 @ViewDebug.ExportedProperty(category="recents") 145 public boolean useLightOnPrimaryColor; 146 147 /** 148 * The task description for this task, only used to reload task icons. 149 */ 150 public TaskDescription taskDescription; 151 152 /** 153 * The state isLaunchTarget will be set for the correct task upon launching Recents. 154 */ 155 @ViewDebug.ExportedProperty(category="recents") 156 public boolean isLaunchTarget; 157 @ViewDebug.ExportedProperty(category="recents") 158 public boolean isStackTask; 159 @ViewDebug.ExportedProperty(category="recents") 160 public boolean isSystemApp; 161 @ViewDebug.ExportedProperty(category="recents") 162 public boolean isDockable; 163 164 /** 165 * Resize mode. See {@link ActivityInfo#resizeMode}. 166 */ 167 @ViewDebug.ExportedProperty(category="recents") 168 public int resizeMode; 169 170 @ViewDebug.ExportedProperty(category="recents") 171 public ComponentName topActivity; 172 173 @ViewDebug.ExportedProperty(category="recents") 174 public boolean isLocked; 175 176 private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>(); 177 Task()178 public Task() { 179 // Do nothing 180 } 181 Task(TaskKey key, Drawable icon, ThumbnailData thumbnail, String title, String titleDescription, int colorPrimary, int colorBackground, boolean isLaunchTarget, boolean isStackTask, boolean isSystemApp, boolean isDockable, TaskDescription taskDescription, int resizeMode, ComponentName topActivity, boolean isLocked)182 public Task(TaskKey key, Drawable icon, ThumbnailData thumbnail, String title, 183 String titleDescription, int colorPrimary, int colorBackground, boolean isLaunchTarget, 184 boolean isStackTask, boolean isSystemApp, boolean isDockable, 185 TaskDescription taskDescription, int resizeMode, ComponentName topActivity, 186 boolean isLocked) { 187 this.key = key; 188 this.icon = icon; 189 this.thumbnail = thumbnail; 190 this.title = title; 191 this.titleDescription = titleDescription; 192 this.colorPrimary = colorPrimary; 193 this.colorBackground = colorBackground; 194 this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary, 195 Color.WHITE) > 3f; 196 this.taskDescription = taskDescription; 197 this.isLaunchTarget = isLaunchTarget; 198 this.isStackTask = isStackTask; 199 this.isSystemApp = isSystemApp; 200 this.isDockable = isDockable; 201 this.resizeMode = resizeMode; 202 this.topActivity = topActivity; 203 this.isLocked = isLocked; 204 } 205 206 /** 207 * Copies the metadata from another task, but retains the current callbacks. 208 */ copyFrom(Task o)209 public void copyFrom(Task o) { 210 this.key = o.key; 211 this.icon = o.icon; 212 this.thumbnail = o.thumbnail; 213 this.title = o.title; 214 this.titleDescription = o.titleDescription; 215 this.colorPrimary = o.colorPrimary; 216 this.colorBackground = o.colorBackground; 217 this.useLightOnPrimaryColor = o.useLightOnPrimaryColor; 218 this.taskDescription = o.taskDescription; 219 this.isLaunchTarget = o.isLaunchTarget; 220 this.isStackTask = o.isStackTask; 221 this.isSystemApp = o.isSystemApp; 222 this.isDockable = o.isDockable; 223 this.resizeMode = o.resizeMode; 224 this.isLocked = o.isLocked; 225 this.topActivity = o.topActivity; 226 } 227 228 /** 229 * Add a callback. 230 */ addCallback(TaskCallbacks cb)231 public void addCallback(TaskCallbacks cb) { 232 if (!mCallbacks.contains(cb)) { 233 mCallbacks.add(cb); 234 } 235 } 236 237 /** 238 * Remove a callback. 239 */ removeCallback(TaskCallbacks cb)240 public void removeCallback(TaskCallbacks cb) { 241 mCallbacks.remove(cb); 242 } 243 244 /** Updates the task's windowing mode. */ setWindowingMode(int windowingMode)245 public void setWindowingMode(int windowingMode) { 246 key.setWindowingMode(windowingMode); 247 int callbackCount = mCallbacks.size(); 248 for (int i = 0; i < callbackCount; i++) { 249 mCallbacks.get(i).onTaskWindowingModeChanged(); 250 } 251 } 252 253 /** Notifies the callback listeners that this task has been loaded */ notifyTaskDataLoaded(ThumbnailData thumbnailData, Drawable applicationIcon)254 public void notifyTaskDataLoaded(ThumbnailData thumbnailData, Drawable applicationIcon) { 255 this.icon = applicationIcon; 256 this.thumbnail = thumbnailData; 257 int callbackCount = mCallbacks.size(); 258 for (int i = 0; i < callbackCount; i++) { 259 mCallbacks.get(i).onTaskDataLoaded(this, thumbnailData); 260 } 261 } 262 263 /** Notifies the callback listeners that this task has been unloaded */ notifyTaskDataUnloaded(Drawable defaultApplicationIcon)264 public void notifyTaskDataUnloaded(Drawable defaultApplicationIcon) { 265 icon = defaultApplicationIcon; 266 thumbnail = null; 267 for (int i = mCallbacks.size() - 1; i >= 0; i--) { 268 mCallbacks.get(i).onTaskDataUnloaded(); 269 } 270 } 271 272 /** 273 * Returns the top activity component. 274 */ getTopComponent()275 public ComponentName getTopComponent() { 276 return topActivity != null 277 ? topActivity 278 : key.baseIntent.getComponent(); 279 } 280 281 @Override equals(Object o)282 public boolean equals(Object o) { 283 // Check that the id matches 284 Task t = (Task) o; 285 return key.equals(t.key); 286 } 287 288 @Override toString()289 public String toString() { 290 return "[" + key.toString() + "] " + title; 291 } 292 dump(String prefix, PrintWriter writer)293 public void dump(String prefix, PrintWriter writer) { 294 writer.print(prefix); writer.print(key); 295 if (!isDockable) { 296 writer.print(" dockable=N"); 297 } 298 if (isLaunchTarget) { 299 writer.print(" launchTarget=Y"); 300 } 301 if (isLocked) { 302 writer.print(" locked=Y"); 303 } 304 writer.print(" "); writer.print(title); 305 writer.println(); 306 } 307 } 308