• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.phone.vvm.omtp.scheduling;
18 
19 import android.annotation.CallSuper;
20 import android.annotation.MainThread;
21 import android.annotation.WorkerThread;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.SystemClock;
25 import android.support.annotation.NonNull;
26 import android.telephony.SubscriptionManager;
27 import com.android.phone.Assert;
28 import com.android.phone.NeededForTesting;
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  * Provides common utilities for task implementations, such as execution time and managing {@link
34  * Policy}
35  */
36 public abstract class BaseTask implements Task {
37 
38     private static final String EXTRA_SUB_ID = "extra_sub_id";
39 
40     private Context mContext;
41 
42     private int mId;
43     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
44 
45     private boolean mHasStarted;
46     private volatile boolean mHasFailed;
47 
48     @NonNull
49     private final List<Policy> mPolicies = new ArrayList<>();
50 
51     private long mExecutionTime;
52 
53     private static Clock sClock = new Clock();
54 
BaseTask(int id)55     protected BaseTask(int id) {
56         mId = id;
57         mExecutionTime = getTimeMillis();
58     }
59 
60     /**
61      * Modify the task ID to prevent arbitrary task from executing. Can only be called before {@link
62      * #onCreate(Context, Intent, int, int)} returns.
63      */
64     @MainThread
setId(int id)65     public void setId(int id) {
66         Assert.isMainThread();
67         mId = id;
68     }
69 
70     @MainThread
hasStarted()71     public boolean hasStarted() {
72         Assert.isMainThread();
73         return mHasStarted;
74     }
75 
76     @MainThread
hasFailed()77     public boolean hasFailed() {
78         Assert.isMainThread();
79         return mHasFailed;
80     }
81 
getContext()82     public Context getContext() {
83         return mContext;
84     }
85 
getSubId()86     public int getSubId() {
87         return mSubId;
88     }
89     /**
90      * Should be call in the constructor or {@link Policy#onCreate(BaseTask, Intent, int, int)} will
91      * be missed.
92      */
93     @MainThread
addPolicy(Policy policy)94     public BaseTask addPolicy(Policy policy) {
95         Assert.isMainThread();
96         mPolicies.add(policy);
97         return this;
98     }
99 
100     /**
101      * Indicate the task has failed. {@link Policy#onFail()} will be triggered once the execution
102      * ends. This mechanism is used by policies for actions such as determining whether to schedule
103      * a retry. Must be call inside {@link #onExecuteInBackgroundThread()}
104      */
105     @WorkerThread
fail()106     public void fail() {
107         Assert.isNotMainThread();
108         mHasFailed = true;
109     }
110 
111     @MainThread
setExecutionTime(long timeMillis)112     public void setExecutionTime(long timeMillis) {
113         Assert.isMainThread();
114         mExecutionTime = timeMillis;
115     }
116 
getTimeMillis()117     public long getTimeMillis() {
118         return sClock.getTimeMillis();
119     }
120 
121     /**
122      * Creates an intent that can be used to restart the current task. Derived class should build
123      * their intent upon this.
124      */
createRestartIntent()125     public Intent createRestartIntent() {
126         return createIntent(getContext(), this.getClass(), mSubId);
127     }
128 
129     /**
130      * Creates an intent that can be used to start the {@link TaskSchedulerService}. Derived class
131      * should build their intent upon this.
132      */
createIntent(Context context, Class<? extends BaseTask> task, int subId)133     public static Intent createIntent(Context context, Class<? extends BaseTask> task, int subId) {
134         Intent intent = TaskSchedulerService.createIntent(context, task);
135         intent.putExtra(EXTRA_SUB_ID, subId);
136         return intent;
137     }
138 
139     @Override
getId()140     public TaskId getId() {
141         return new TaskId(mId, mSubId);
142     }
143 
144     @Override
145     @CallSuper
onCreate(Context context, Intent intent, int flags, int startId)146     public void onCreate(Context context, Intent intent, int flags, int startId) {
147         mContext = context;
148         mSubId = intent.getIntExtra(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
149         for (Policy policy : mPolicies) {
150             policy.onCreate(this, intent, flags, startId);
151         }
152     }
153 
154     @Override
getReadyInMilliSeconds()155     public long getReadyInMilliSeconds() {
156         return mExecutionTime - getTimeMillis();
157     }
158 
159     @Override
160     @CallSuper
onBeforeExecute()161     public void onBeforeExecute() {
162         for (Policy policy : mPolicies) {
163             policy.onBeforeExecute();
164         }
165         mHasStarted = true;
166     }
167 
168     @Override
169     @CallSuper
onCompleted()170     public void onCompleted() {
171         if (mHasFailed) {
172             for (Policy policy : mPolicies) {
173                 policy.onFail();
174             }
175         }
176 
177         for (Policy policy : mPolicies) {
178             policy.onCompleted();
179         }
180     }
181 
182     @Override
onDuplicatedTaskAdded(Task task)183     public void onDuplicatedTaskAdded(Task task) {
184         for (Policy policy : mPolicies) {
185             policy.onDuplicatedTaskAdded();
186         }
187     }
188 
189     @NeededForTesting
190     static class Clock {
191 
getTimeMillis()192         public long getTimeMillis() {
193             return SystemClock.elapsedRealtime();
194         }
195     }
196 
197     /**
198      * Used to replace the clock with an deterministic clock
199      */
200     @NeededForTesting
setClockForTesting(Clock clock)201     static void setClockForTesting(Clock clock) {
202         sClock = clock;
203     }
204 }
205