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