1 /*
2  * Copyright (C) 2017 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.voicemail.impl.scheduling;
18 
19 import android.annotation.TargetApi;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.Build.VERSION_CODES;
24 import android.os.Bundle;
25 import com.android.voicemail.impl.VvmLog;
26 import com.android.voicemail.impl.scheduling.Tasks.TaskCreationException;
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 /**
31  * BroadcastReceiver to queue and run {@link Task} with the {@link android.app.job.JobScheduler}. A
32  * task is queued using a explicit broadcast to this receiver. The intent should contain enough
33  * information in {@link Intent#getExtras()} to construct the task (see {@link
34  * Tasks#createIntent(Context, Class)}). The task will be queued directly in {@link TaskExecutor} if
35  * it is already running, or in {@link TaskSchedulerJobService} if not.
36  */
37 @TargetApi(VERSION_CODES.O)
38 public class TaskReceiver extends BroadcastReceiver {
39 
40   private static final String TAG = "VvmTaskReceiver";
41 
42   private static final List<Intent> deferredBroadcasts = new ArrayList<>();
43 
44   /**
45    * When {@link TaskExecutor#isTerminating()} is {@code true}, newly added tasks will be deferred
46    * to allow the TaskExecutor to terminate properly. After termination is completed this should be
47    * called to add the tasks again.
48    */
resendDeferredBroadcasts(Context context)49   public static void resendDeferredBroadcasts(Context context) {
50     for (Intent intent : deferredBroadcasts) {
51       context.sendBroadcast(intent);
52     }
53     deferredBroadcasts.clear();
54   }
55 
56   @Override
onReceive(Context context, Intent intent)57   public void onReceive(Context context, Intent intent) {
58     if (intent == null) {
59       VvmLog.w(TAG, "null intent received");
60       return;
61     }
62     VvmLog.i(TAG, "task received");
63     TaskExecutor taskExecutor = TaskExecutor.getRunningInstance();
64     if (taskExecutor != null) {
65       VvmLog.i(TAG, "TaskExecutor already running");
66       if (taskExecutor.isTerminating()) {
67         // The current taskExecutor and cannot do anything and a new job cannot be scheduled. Defer
68         // the task until a new job can be scheduled.
69         VvmLog.w(TAG, "TaskExecutor is terminating, bouncing task");
70         deferredBroadcasts.add(intent);
71         return;
72       }
73       try {
74         Task task = Tasks.createTask(context.getApplicationContext(), intent.getExtras());
75         taskExecutor.addTask(task);
76       } catch (TaskCreationException e) {
77         VvmLog.e(TAG, "cannot create task", e);
78       }
79     } else {
80       VvmLog.i(TAG, "scheduling new job");
81       List<Bundle> taskList = new ArrayList<>();
82       taskList.add(intent.getExtras());
83       TaskSchedulerJobService.scheduleJob(context.getApplicationContext(), taskList, 0, true);
84     }
85   }
86 }
87