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
17package com.android.systemui.recents.model;
18
19import android.content.ComponentName;
20import android.content.Intent;
21import android.graphics.Bitmap;
22import android.graphics.Color;
23import android.graphics.drawable.Drawable;
24import com.android.systemui.recents.misc.Utilities;
25
26import java.util.Objects;
27
28
29/**
30 * A task represents the top most task in the system's task stack.
31 */
32public class Task {
33    /* Task callbacks */
34    public interface TaskCallbacks {
35        /* Notifies when a task has been bound */
36        public void onTaskDataLoaded();
37        /* Notifies when a task has been unbound */
38        public void onTaskDataUnloaded();
39    }
40
41    /** The ComponentNameKey represents the unique primary key for a component
42     * belonging to a specified user. */
43    public static class ComponentNameKey {
44        final ComponentName component;
45        final int userId;
46
47        public ComponentNameKey(ComponentName cn, int user) {
48            component = cn;
49            userId = user;
50        }
51
52        @Override
53        public int hashCode() {
54            return Objects.hash(component, userId);
55        }
56
57        @Override
58        public boolean equals(Object o) {
59            if (!(o instanceof ComponentNameKey)) {
60                return false;
61            }
62            return component.equals(((ComponentNameKey) o).component) &&
63                    userId == ((ComponentNameKey) o).userId;
64        }
65    }
66
67    /* The Task Key represents the unique primary key for the task */
68    public static class TaskKey {
69        final ComponentNameKey mComponentNameKey;
70        public final int id;
71        public final Intent baseIntent;
72        public final int userId;
73        public long firstActiveTime;
74        public long lastActiveTime;
75
76        public TaskKey(int id, Intent intent, int userId, long firstActiveTime, long lastActiveTime) {
77            mComponentNameKey = new ComponentNameKey(intent.getComponent(), userId);
78            this.id = id;
79            this.baseIntent = intent;
80            this.userId = userId;
81            this.firstActiveTime = firstActiveTime;
82            this.lastActiveTime = lastActiveTime;
83        }
84
85        /** Returns the component name key for this task. */
86        public ComponentNameKey getComponentNameKey() {
87            return mComponentNameKey;
88        }
89
90        @Override
91        public boolean equals(Object o) {
92            if (!(o instanceof TaskKey)) {
93                return false;
94            }
95            return id == ((TaskKey) o).id
96                    && userId == ((TaskKey) o).userId;
97        }
98
99        @Override
100        public int hashCode() {
101            return (id << 5) + userId;
102        }
103
104        @Override
105        public String toString() {
106            return "Task.Key: " + id + ", "
107                    + "u: " + userId + ", "
108                    + "lat: " + lastActiveTime + ", "
109                    + baseIntent.getComponent().getPackageName();
110        }
111    }
112
113    public TaskKey key;
114    public TaskGrouping group;
115    public int taskAffiliation;
116    public int taskAffiliationColor;
117    public boolean isLaunchTarget;
118    public Drawable applicationIcon;
119    public Drawable activityIcon;
120    public String activityLabel;
121    public int colorPrimary;
122    public boolean useLightOnPrimaryColor;
123    public Bitmap thumbnail;
124    public boolean isActive;
125    public boolean lockToThisTask;
126    public boolean lockToTaskEnabled;
127    public Bitmap icon;
128    public String iconFilename;
129    TaskCallbacks mCb;
130
131    public Task() {
132        // Only used by RecentsService for task rect calculations.
133    }
134
135    public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
136                String activityTitle, Drawable activityIcon, int colorPrimary,
137                boolean lockToThisTask, boolean lockToTaskEnabled, Bitmap icon,
138                String iconFilename) {
139        boolean isInAffiliationGroup = (taskAffiliation != key.id);
140        boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
141        this.key = key;
142        this.taskAffiliation = taskAffiliation;
143        this.taskAffiliationColor = taskAffiliationColor;
144        this.activityLabel = activityTitle;
145        this.activityIcon = activityIcon;
146        this.colorPrimary = hasAffiliationGroupColor ? taskAffiliationColor : colorPrimary;
147        this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
148                Color.WHITE) > 3f;
149        this.isActive = isActive;
150        this.lockToThisTask = lockToTaskEnabled && lockToThisTask;
151        this.lockToTaskEnabled = lockToTaskEnabled;
152        this.icon = icon;
153        this.iconFilename = iconFilename;
154    }
155
156    /** Copies the other task. */
157    public void copyFrom(Task o) {
158        this.key = o.key;
159        this.taskAffiliation = o.taskAffiliation;
160        this.taskAffiliationColor = o.taskAffiliationColor;
161        this.activityLabel = o.activityLabel;
162        this.activityIcon = o.activityIcon;
163        this.colorPrimary = o.colorPrimary;
164        this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
165        this.isActive = o.isActive;
166        this.lockToThisTask = o.lockToThisTask;
167        this.lockToTaskEnabled = o.lockToTaskEnabled;
168    }
169
170    /** Set the callbacks */
171    public void setCallbacks(TaskCallbacks cb) {
172        mCb = cb;
173    }
174
175    /** Set the grouping */
176    public void setGroup(TaskGrouping group) {
177        if (group != null && this.group != null) {
178            throw new RuntimeException("This task is already assigned to a group.");
179        }
180        this.group = group;
181    }
182
183    /** Notifies the callback listeners that this task has been loaded */
184    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon) {
185        this.applicationIcon = applicationIcon;
186        this.thumbnail = thumbnail;
187        if (mCb != null) {
188            mCb.onTaskDataLoaded();
189        }
190    }
191
192    /** Notifies the callback listeners that this task has been unloaded */
193    public void notifyTaskDataUnloaded(Bitmap defaultThumbnail, Drawable defaultApplicationIcon) {
194        applicationIcon = defaultApplicationIcon;
195        thumbnail = defaultThumbnail;
196        if (mCb != null) {
197            mCb.onTaskDataUnloaded();
198        }
199    }
200
201    @Override
202    public boolean equals(Object o) {
203        // Check that the id matches
204        Task t = (Task) o;
205        return key.equals(t.key);
206    }
207
208    @Override
209    public String toString() {
210        String groupAffiliation = "no group";
211        if (group != null) {
212            groupAffiliation = Integer.toString(group.affiliation);
213        }
214        return "Task (" + groupAffiliation + "): " + key.baseIntent.getComponent().getPackageName() +
215                " [" + super.toString() + "]";
216    }
217}
218