blob: f72ab22f546c90f14b1bf7925bdd47a939722075 [file] [log] [blame]
Matthew Williams691e93e2014-05-12 15:33:09 -07001/*
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.server.task;
18
Christopher Tate8f64f802014-05-19 13:46:29 -070019import android.app.task.Task;
Matthew Williams691e93e2014-05-12 15:33:09 -070020import android.content.Context;
Matthew Williamsb61c5062014-05-14 11:06:04 -070021import android.util.ArraySet;
22import android.util.Slog;
Matthew Williams691e93e2014-05-12 15:33:09 -070023import android.util.SparseArray;
24
25import com.android.server.task.controllers.TaskStatus;
26
Matthew Williamsb61c5062014-05-14 11:06:04 -070027import java.util.HashSet;
28import java.util.Iterator;
29import java.util.Set;
30
Matthew Williams691e93e2014-05-12 15:33:09 -070031/**
32 * Maintain a list of classes, and accessor methods/logic for these tasks.
33 * This class offers the following functionality:
34 * - When a task is added, it will determine if the task requirements have changed (update) and
35 * whether the controllers need to be updated.
36 * - Persists Tasks, figures out when to to rewrite the Task to disk.
37 * - Is threadsafe.
38 * - Handles rescheduling of tasks.
39 * - When a periodic task is executed and must be re-added.
40 * - When a task fails and the client requests that it be retried with backoff.
41 * - This class is <strong>not</strong> thread-safe.
42 */
43public class TaskStore {
Matthew Williamsb61c5062014-05-14 11:06:04 -070044 private static final String TAG = "TaskManagerStore";
45 /** Threshold to adjust how often we want to write to the db. */
46 private static final int MAX_OPS_BEFORE_WRITE = 1;
47 final ArraySet<TaskStatus> mTasks;
Matthew Williams691e93e2014-05-12 15:33:09 -070048 final Context mContext;
49
Matthew Williamsb61c5062014-05-14 11:06:04 -070050 private int mDirtyOperations;
51
Matthew Williams691e93e2014-05-12 15:33:09 -070052 TaskStore(Context context) {
Matthew Williamsb61c5062014-05-14 11:06:04 -070053 mTasks = intialiseTasksFromDisk();
Matthew Williams691e93e2014-05-12 15:33:09 -070054 mContext = context;
Matthew Williamsb61c5062014-05-14 11:06:04 -070055 mDirtyOperations = 0;
Matthew Williams691e93e2014-05-12 15:33:09 -070056 }
57
58 /**
Matthew Williamsb61c5062014-05-14 11:06:04 -070059 * Add a task to the master list, persisting it if necessary. If the TaskStatus already exists,
60 * it will be replaced.
61 * @param taskStatus Task to add.
62 * @return true if the operation succeeded.
Matthew Williams691e93e2014-05-12 15:33:09 -070063 */
Matthew Williamsb61c5062014-05-14 11:06:04 -070064 public boolean add(TaskStatus taskStatus) {
65 if (taskStatus.isPersisted()) {
66 if (!maybeWriteStatusToDisk()) {
67 return false;
Matthew Williams691e93e2014-05-12 15:33:09 -070068 }
69 }
Matthew Williamsb61c5062014-05-14 11:06:04 -070070 mTasks.remove(taskStatus);
71 mTasks.add(taskStatus);
72 return true;
73 }
74
75 public int size() {
76 return mTasks.size();
Matthew Williams691e93e2014-05-12 15:33:09 -070077 }
78
79 /**
Matthew Williamsb61c5062014-05-14 11:06:04 -070080 * Remove the provided task. Will also delete the task if it was persisted.
81 * @return The TaskStatus that was removed, or null if an invalid token was provided.
Matthew Williams691e93e2014-05-12 15:33:09 -070082 */
Matthew Williamsb61c5062014-05-14 11:06:04 -070083 public boolean remove(TaskStatus taskStatus) {
84 boolean removed = mTasks.remove(taskStatus);
85 if (!removed) {
86 Slog.e(TAG, "Error removing task: " + taskStatus);
87 return false;
88 } else {
89 maybeWriteStatusToDisk();
90 }
91 return true;
92 }
Matthew Williams691e93e2014-05-12 15:33:09 -070093
Matthew Williamsb61c5062014-05-14 11:06:04 -070094 /**
95 * Removes all TaskStatus objects for a given uid from the master list. Note that it is
96 * possible to remove a task that is pending/active. This operation will succeed, and the
97 * removal will take effect when the task has completed executing.
98 * @param uid Uid of the requesting app.
99 * @return True if at least one task was removed, false if nothing matching the provided uId
100 * was found.
101 */
102 public boolean removeAllByUid(int uid) {
103 Iterator<TaskStatus> it = mTasks.iterator();
104 boolean removed = false;
105 while (it.hasNext()) {
106 TaskStatus ts = it.next();
107 if (ts.getUid() == uid) {
108 it.remove();
109 removed = true;
110 }
111 }
112 if (removed) {
113 maybeWriteStatusToDisk();
114 }
115 return removed;
116 }
117
118 /**
119 * Remove the TaskStatus that matches the provided uId and taskId. Note that it is possible
120 * to remove a task that is pending/active. This operation will succeed, and the removal will
121 * take effect when the task has completed executing.
122 * @param uid Uid of the requesting app.
123 * @param taskId Task id, specified at schedule-time.
124 * @return true if a removal occurred, false if the provided parameters didn't match anything.
125 */
126 public boolean remove(int uid, int taskId) {
127 Iterator<TaskStatus> it = mTasks.iterator();
128 while (it.hasNext()) {
129 TaskStatus ts = it.next();
130 if (ts.getUid() == uid && ts.getTaskId() == taskId) {
131 it.remove();
132 maybeWriteStatusToDisk();
133 return true;
134 }
135 }
136 return false;
137 }
138
139 /**
140 * @return The live array of TaskStatus objects.
141 */
142 public Set<TaskStatus> getTasks() {
143 return mTasks;
Matthew Williams691e93e2014-05-12 15:33:09 -0700144 }
145
146 /**
147 * Every time the state changes we write all the tasks in one swathe, instead of trying to
148 * track incremental changes.
Matthew Williamsb61c5062014-05-14 11:06:04 -0700149 * @return Whether the operation was successful. This will only fail for e.g. if the system is
150 * low on storage. If this happens, we continue as normal
Matthew Williams691e93e2014-05-12 15:33:09 -0700151 */
Matthew Williamsb61c5062014-05-14 11:06:04 -0700152 private boolean maybeWriteStatusToDisk() {
153 mDirtyOperations++;
154 if (mDirtyOperations > MAX_OPS_BEFORE_WRITE) {
155 for (TaskStatus ts : mTasks) {
156 //
157 }
158 mDirtyOperations = 0;
159 }
Matthew Williams691e93e2014-05-12 15:33:09 -0700160 return true;
161 }
162
163 /**
164 *
165 * @return
166 */
167 // TODO: Implement this.
Matthew Williamsb61c5062014-05-14 11:06:04 -0700168 private ArraySet<TaskStatus> intialiseTasksFromDisk() {
169 return new ArraySet<TaskStatus>();
Matthew Williams691e93e2014-05-12 15:33:09 -0700170 }
171}