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