• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.app;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.RequiresPermission;
22 import android.app.job.IJobScheduler;
23 import android.app.job.IUserVisibleJobObserver;
24 import android.app.job.JobInfo;
25 import android.app.job.JobScheduler;
26 import android.app.job.JobSnapshot;
27 import android.app.job.JobWorkItem;
28 import android.app.job.PendingJobReasonsInfo;
29 import android.content.Context;
30 import android.content.pm.ParceledListSlice;
31 import android.os.RemoteException;
32 import android.util.ArrayMap;
33 
34 import java.util.Collections;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38 
39 /**
40  * Concrete implementation of the JobScheduler interface
41  *
42  * Note android.app.job is the better package to put this class, but we can't move it there
43  * because that'd break robolectric. Grr.
44  *
45  * @hide
46  */
47 public class JobSchedulerImpl extends JobScheduler {
48     IJobScheduler mBinder;
49     private final Context mContext;
50     private final String mNamespace;
51 
JobSchedulerImpl(@onNull Context context, IJobScheduler binder)52     public JobSchedulerImpl(@NonNull Context context, IJobScheduler binder) {
53         this(context, binder, null);
54     }
55 
JobSchedulerImpl(@onNull Context context, IJobScheduler binder, @Nullable String namespace)56     private JobSchedulerImpl(@NonNull Context context, IJobScheduler binder,
57             @Nullable String namespace) {
58         mContext = context;
59         mBinder = binder;
60         mNamespace = namespace;
61     }
62 
JobSchedulerImpl(JobSchedulerImpl jsi, @Nullable String namespace)63     private JobSchedulerImpl(JobSchedulerImpl jsi, @Nullable String namespace) {
64         this(jsi.mContext, jsi.mBinder, namespace);
65     }
66 
67     @NonNull
68     @Override
forNamespace(@onNull String namespace)69     public JobScheduler forNamespace(@NonNull String namespace) {
70         namespace = sanitizeNamespace(namespace);
71         if (namespace == null) {
72             throw new NullPointerException("namespace cannot be null");
73         }
74         if (namespace.isEmpty()) {
75             throw new IllegalArgumentException("namespace cannot be empty");
76         }
77         return new JobSchedulerImpl(this, namespace);
78     }
79 
80     @Nullable
81     @Override
getNamespace()82     public String getNamespace() {
83         return mNamespace;
84     }
85 
86     @Override
schedule(JobInfo job)87     public int schedule(JobInfo job) {
88         try {
89             return mBinder.schedule(mNamespace, job);
90         } catch (RemoteException e) {
91             return JobScheduler.RESULT_FAILURE;
92         }
93     }
94 
95     @Override
enqueue(JobInfo job, JobWorkItem work)96     public int enqueue(JobInfo job, JobWorkItem work) {
97         try {
98             return mBinder.enqueue(mNamespace, job, work);
99         } catch (RemoteException e) {
100             return JobScheduler.RESULT_FAILURE;
101         }
102     }
103 
104     @Override
scheduleAsPackage(JobInfo job, String packageName, int userId, String tag)105     public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag) {
106         try {
107             return mBinder.scheduleAsPackage(mNamespace, job, packageName, userId, tag);
108         } catch (RemoteException e) {
109             return JobScheduler.RESULT_FAILURE;
110         }
111     }
112 
113     @Override
cancel(int jobId)114     public void cancel(int jobId) {
115         try {
116             mBinder.cancel(mNamespace, jobId);
117         } catch (RemoteException e) {}
118     }
119 
120     @Override
cancelAll()121     public void cancelAll() {
122         try {
123             mBinder.cancelAllInNamespace(mNamespace);
124         } catch (RemoteException e) {}
125     }
126 
127     @Override
cancelInAllNamespaces()128     public void cancelInAllNamespaces() {
129         try {
130             mBinder.cancelAll();
131         } catch (RemoteException e) {}
132     }
133 
134     @Override
getAllPendingJobs()135     public List<JobInfo> getAllPendingJobs() {
136         try {
137             return mBinder.getAllPendingJobsInNamespace(mNamespace).getList();
138         } catch (RemoteException e) {
139             return null;
140         }
141     }
142 
143     @Override
getPendingJobsInAllNamespaces()144     public Map<String, List<JobInfo>> getPendingJobsInAllNamespaces() {
145         try {
146             final Map<String, ParceledListSlice<JobInfo>> parceledList =
147                     mBinder.getAllPendingJobs();
148             final ArrayMap<String, List<JobInfo>> jobMap = new ArrayMap<>();
149             final Set<String> keys = parceledList.keySet();
150             for (String key : keys) {
151                 jobMap.put(key, parceledList.get(key).getList());
152             }
153             return jobMap;
154         } catch (RemoteException e) {
155             return null;
156         }
157     }
158 
159     @Override
getPendingJob(int jobId)160     public JobInfo getPendingJob(int jobId) {
161         try {
162             return mBinder.getPendingJob(mNamespace, jobId);
163         } catch (RemoteException e) {
164             return null;
165         }
166     }
167 
168     @Override
getPendingJobReason(int jobId)169     public int getPendingJobReason(int jobId) {
170         try {
171             return mBinder.getPendingJobReason(mNamespace, jobId);
172         } catch (RemoteException e) {
173             return PENDING_JOB_REASON_UNDEFINED;
174         }
175     }
176 
177     @Override
178     @NonNull
getPendingJobReasons(int jobId)179     public int[] getPendingJobReasons(int jobId) {
180         try {
181             return mBinder.getPendingJobReasons(mNamespace, jobId);
182         } catch (RemoteException e) {
183             return new int[] { PENDING_JOB_REASON_UNDEFINED };
184         }
185     }
186 
187     @Override
188     @NonNull
getPendingJobReasonsHistory(int jobId)189     public List<PendingJobReasonsInfo> getPendingJobReasonsHistory(int jobId) {
190         try {
191             return mBinder.getPendingJobReasonsHistory(mNamespace, jobId);
192         } catch (RemoteException e) {
193             return Collections.EMPTY_LIST;
194         }
195     }
196 
197     @Override
canRunUserInitiatedJobs()198     public boolean canRunUserInitiatedJobs() {
199         try {
200             return mBinder.canRunUserInitiatedJobs(mContext.getOpPackageName());
201         } catch (RemoteException e) {
202             return false;
203         }
204     }
205 
206     @Override
hasRunUserInitiatedJobsPermission(String packageName, int userId)207     public boolean hasRunUserInitiatedJobsPermission(String packageName, int userId) {
208         try {
209             return mBinder.hasRunUserInitiatedJobsPermission(packageName, userId);
210         } catch (RemoteException e) {
211             return false;
212         }
213     }
214 
215     @Override
getStartedJobs()216     public List<JobInfo> getStartedJobs() {
217         try {
218             return mBinder.getStartedJobs();
219         } catch (RemoteException e) {
220             return null;
221         }
222     }
223 
224     @Override
getAllJobSnapshots()225     public List<JobSnapshot> getAllJobSnapshots() {
226         try {
227             return mBinder.getAllJobSnapshots().getList();
228         } catch (RemoteException e) {
229             return null;
230         }
231     }
232 
233     @RequiresPermission(allOf = {
234             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
235             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
236     @Override
registerUserVisibleJobObserver(@onNull IUserVisibleJobObserver observer)237     public void registerUserVisibleJobObserver(@NonNull IUserVisibleJobObserver observer) {
238         try {
239             mBinder.registerUserVisibleJobObserver(observer);
240         } catch (RemoteException e) {
241         }
242     }
243 
244     @RequiresPermission(allOf = {
245             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
246             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
247     @Override
unregisterUserVisibleJobObserver(@onNull IUserVisibleJobObserver observer)248     public void unregisterUserVisibleJobObserver(@NonNull IUserVisibleJobObserver observer) {
249         try {
250             mBinder.unregisterUserVisibleJobObserver(observer);
251         } catch (RemoteException e) {
252         }
253     }
254 
255     @RequiresPermission(allOf = {
256             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
257             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
258     @Override
notePendingUserRequestedAppStop(@onNull String packageName, int userId, @Nullable String debugReason)259     public void notePendingUserRequestedAppStop(@NonNull String packageName, int userId,
260             @Nullable String debugReason) {
261         try {
262             mBinder.notePendingUserRequestedAppStop(packageName, userId, debugReason);
263         } catch (RemoteException e) {
264         }
265     }
266 }
267