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 com.android.server.job.controllers;
18 
19 import static com.android.server.job.JobSchedulerService.DEBUG;
20 
21 import android.content.Context;
22 import android.util.Slog;
23 import android.util.proto.ProtoOutputStream;
24 
25 import com.android.internal.util.IndentingPrintWriter;
26 import com.android.server.job.JobSchedulerService;
27 import com.android.server.job.JobSchedulerService.Constants;
28 import com.android.server.job.StateChangedListener;
29 
30 import java.util.function.Predicate;
31 
32 /**
33  * Incorporates shared controller logic between the various controllers of the JobManager.
34  * These are solely responsible for tracking a list of jobs, and notifying the JM when these
35  * are ready to run, or whether they must be stopped.
36  */
37 public abstract class StateController {
38     private static final String TAG = "JobScheduler.SC";
39 
40     protected final JobSchedulerService mService;
41     protected final StateChangedListener mStateChangedListener;
42     protected final Context mContext;
43     protected final Object mLock;
44     protected final Constants mConstants;
45 
StateController(JobSchedulerService service)46     StateController(JobSchedulerService service) {
47         mService = service;
48         mStateChangedListener = service;
49         mContext = service.getTestableContext();
50         mLock = service.getLock();
51         mConstants = service.getConstants();
52     }
53 
54     /**
55      * Called when the system boot phase has reached
56      * {@link com.android.server.SystemService#PHASE_SYSTEM_SERVICES_READY}.
57      */
onSystemServicesReady()58     public void onSystemServicesReady() {
59     }
60 
61     /**
62      * Implement the logic here to decide whether a job should be tracked by this controller.
63      * This logic is put here so the JobManager can be completely agnostic of Controller logic.
64      * Also called when updating a task, so implementing controllers have to be aware of
65      * preexisting tasks.
66      */
maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob)67     public abstract void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob);
68 
69     /**
70      * Optionally implement logic here to prepare the job to be executed.
71      */
prepareForExecutionLocked(JobStatus jobStatus)72     public void prepareForExecutionLocked(JobStatus jobStatus) {
73     }
74 
75     /**
76      * Remove task - this will happen if the task is cancelled, completed, etc.
77      */
maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate)78     public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
79             boolean forUpdate);
80 
81     /**
82      * Called when a new job is being created to reschedule an old failed job.
83      */
rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule)84     public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) {
85     }
86 
87     /**
88      * Called when the JobScheduler.Constants are updated.
89      */
onConstantsUpdatedLocked()90     public void onConstantsUpdatedLocked() {
91     }
92 
93     /** Called when a package is uninstalled from the device (not for an update). */
onAppRemovedLocked(String packageName, int uid)94     public void onAppRemovedLocked(String packageName, int uid) {
95     }
96 
97     /** Called when a user is removed from the device. */
onUserRemovedLocked(int userId)98     public void onUserRemovedLocked(int userId) {
99     }
100 
101     /**
102      * Called when JobSchedulerService has determined that the job is not ready to be run. The
103      * Controller can evaluate if it can or should do something to promote this job's readiness.
104      */
evaluateStateLocked(JobStatus jobStatus)105     public void evaluateStateLocked(JobStatus jobStatus) {
106     }
107 
108     /**
109      * Called when something with the UID has changed. The controller should re-evaluate any
110      * internal state tracking dependent on this UID.
111      */
reevaluateStateLocked(int uid)112     public void reevaluateStateLocked(int uid) {
113     }
114 
wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint)115     protected boolean wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint) {
116         // This is very cheap to check (just a few conditions on data in JobStatus).
117         final boolean jobWouldBeReady = jobStatus.wouldBeReadyWithConstraint(constraint);
118         if (DEBUG) {
119             Slog.v(TAG, "wouldBeReadyWithConstraintLocked: " + jobStatus.toShortString()
120                     + " constraint=" + constraint
121                     + " readyWithConstraint=" + jobWouldBeReady);
122         }
123         if (!jobWouldBeReady) {
124             // If the job wouldn't be ready, nothing to do here.
125             return false;
126         }
127 
128         // This is potentially more expensive since JSS may have to query component
129         // presence.
130         return mService.areComponentsInPlaceLocked(jobStatus);
131     }
132 
dumpControllerStateLocked(IndentingPrintWriter pw, Predicate<JobStatus> predicate)133     public abstract void dumpControllerStateLocked(IndentingPrintWriter pw,
134             Predicate<JobStatus> predicate);
dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, Predicate<JobStatus> predicate)135     public abstract void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
136             Predicate<JobStatus> predicate);
137 
138     /** Dump any internal constants the Controller may have. */
dumpConstants(IndentingPrintWriter pw)139     public void dumpConstants(IndentingPrintWriter pw) {
140     }
141 
142     /** Dump any internal constants the Controller may have. */
dumpConstants(ProtoOutputStream proto)143     public void dumpConstants(ProtoOutputStream proto) {
144     }
145 }
146