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.annotation.NonNull; 22 import android.content.Context; 23 import android.provider.DeviceConfig; 24 import android.util.IndentingPrintWriter; 25 import android.util.Slog; 26 import android.util.proto.ProtoOutputStream; 27 28 import com.android.internal.annotations.GuardedBy; 29 import com.android.internal.util.FrameworkStatsLog; 30 import com.android.server.job.JobSchedulerService; 31 import com.android.server.job.JobSchedulerService.Constants; 32 import com.android.server.job.StateChangedListener; 33 34 import java.util.function.Predicate; 35 36 /** 37 * Incorporates shared controller logic between the various controllers of the JobManager. 38 * These are solely responsible for tracking a list of jobs, and notifying the JM when these 39 * are ready to run, or whether they must be stopped. 40 */ 41 public abstract class StateController { 42 private static final String TAG = "JobScheduler.SC"; 43 44 protected final JobSchedulerService mService; 45 protected final StateChangedListener mStateChangedListener; 46 protected final Context mContext; 47 protected final Object mLock; 48 protected final Constants mConstants; 49 StateController(JobSchedulerService service)50 StateController(JobSchedulerService service) { 51 mService = service; 52 mStateChangedListener = service; 53 mContext = service.getTestableContext(); 54 mLock = service.getLock(); 55 mConstants = service.getConstants(); 56 } 57 58 /** 59 * Called to get the controller to start tracking relevant information. This is called before 60 * {@link #onSystemServicesReady()}. 61 */ startTrackingLocked()62 public void startTrackingLocked() {} 63 64 /** 65 * Called when the system boot phase has reached 66 * {@link com.android.server.SystemService#PHASE_SYSTEM_SERVICES_READY}. 67 */ onSystemServicesReady()68 public void onSystemServicesReady() { 69 } 70 71 /** 72 * Implement the logic here to decide whether a job should be tracked by this controller. 73 * This logic is put here so the JobManager can be completely agnostic of Controller logic. 74 * Also called when updating a task, so implementing controllers have to be aware of 75 * preexisting tasks. 76 * This will never be called before {@link #onSystemServicesReady()}. 77 */ maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob)78 public abstract void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob); 79 80 /** 81 * Optionally implement logic here to prepare the job to be executed. 82 */ prepareForExecutionLocked(JobStatus jobStatus)83 public void prepareForExecutionLocked(JobStatus jobStatus) { 84 } 85 86 /** 87 * Optionally implement logic here for when a job that was about to be executed failed to start. 88 */ unprepareFromExecutionLocked(JobStatus jobStatus)89 public void unprepareFromExecutionLocked(JobStatus jobStatus) { 90 } 91 92 /** 93 * Remove task - this will happen if the task is cancelled, completed, etc. 94 */ maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob)95 public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob); 96 97 /** 98 * Called when a new job is being created to reschedule an old failed job. 99 */ rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule)100 public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) { 101 } 102 103 /** Notice that updated configuration constants are about to be read. */ prepareForUpdatedConstantsLocked()104 public void prepareForUpdatedConstantsLocked() {} 105 106 /** Process the specified constant and update internal constants if relevant. */ processConstantLocked(@onNull DeviceConfig.Properties properties, @NonNull String key)107 public void processConstantLocked(@NonNull DeviceConfig.Properties properties, 108 @NonNull String key) {} 109 110 /** 111 * Called when the JobScheduler.Constants are updated. 112 */ onConstantsUpdatedLocked()113 public void onConstantsUpdatedLocked() { 114 } 115 116 /** Called when a package is uninstalled from the device (not for an update). */ onAppRemovedLocked(String packageName, int uid)117 public void onAppRemovedLocked(String packageName, int uid) { 118 } 119 120 /** Called when a user is added to the device. */ onUserAddedLocked(int userId)121 public void onUserAddedLocked(int userId) { 122 } 123 124 /** Called when a user is removed from the device. */ onUserRemovedLocked(int userId)125 public void onUserRemovedLocked(int userId) { 126 } 127 128 /** 129 * Called when JobSchedulerService has determined that the job is not ready to be run. The 130 * Controller can evaluate if it can or should do something to promote this job's readiness. 131 */ evaluateStateLocked(JobStatus jobStatus)132 public void evaluateStateLocked(JobStatus jobStatus) { 133 } 134 135 /** 136 * Called when something with the UID has changed. The controller should re-evaluate any 137 * internal state tracking dependent on this UID. 138 */ reevaluateStateLocked(int uid)139 public void reevaluateStateLocked(int uid) { 140 } 141 142 /** 143 * Called when the battery status changes. 144 */ 145 @GuardedBy("mLock") onBatteryStateChangedLocked()146 public void onBatteryStateChangedLocked() { 147 } 148 149 /** 150 * Called when a UID's base bias has changed. The more positive the bias, the more 151 * important the UID is. 152 */ 153 @GuardedBy("mLock") onUidBiasChangedLocked(int uid, int prevBias, int newBias)154 public void onUidBiasChangedLocked(int uid, int prevBias, int newBias) { 155 } 156 wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint)157 protected boolean wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint) { 158 // This is very cheap to check (just a few conditions on data in JobStatus). 159 final boolean jobWouldBeReady = jobStatus.wouldBeReadyWithConstraint(constraint); 160 if (DEBUG) { 161 Slog.v(TAG, "wouldBeReadyWithConstraintLocked: " + jobStatus.toShortString() 162 + " constraint=" + constraint 163 + " readyWithConstraint=" + jobWouldBeReady); 164 } 165 if (!jobWouldBeReady) { 166 // If the job wouldn't be ready, nothing to do here. 167 return false; 168 } 169 170 // This is potentially more expensive since JSS may have to query component 171 // presence. 172 return mService.areComponentsInPlaceLocked(jobStatus); 173 } 174 logDeviceWideConstraintStateToStatsd(int constraint, boolean satisfied)175 protected void logDeviceWideConstraintStateToStatsd(int constraint, boolean satisfied) { 176 FrameworkStatsLog.write( 177 FrameworkStatsLog.DEVICE_WIDE_JOB_CONSTRAINT_CHANGED, 178 JobStatus.getProtoConstraint(constraint), 179 satisfied 180 ? FrameworkStatsLog.DEVICE_WIDE_JOB_CONSTRAINT_CHANGED__STATE__SATISFIED 181 : FrameworkStatsLog.DEVICE_WIDE_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED); 182 } 183 dumpControllerStateLocked(IndentingPrintWriter pw, Predicate<JobStatus> predicate)184 public abstract void dumpControllerStateLocked(IndentingPrintWriter pw, 185 Predicate<JobStatus> predicate); dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, Predicate<JobStatus> predicate)186 public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, 187 Predicate<JobStatus> predicate) {} 188 189 /** Dump any internal constants the Controller may have. */ dumpConstants(IndentingPrintWriter pw)190 public void dumpConstants(IndentingPrintWriter pw) { 191 } 192 193 /** Dump any internal constants the Controller may have. */ dumpConstants(ProtoOutputStream proto)194 public void dumpConstants(ProtoOutputStream proto) { 195 } 196 197 /** 198 * Standardize the output of userId-packageName combo. 199 */ packageToString(int userId, String packageName)200 static String packageToString(int userId, String packageName) { 201 return "<" + userId + ">" + packageName; 202 } 203 } 204