• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.restrictions;
18 
19 import android.app.job.JobInfo;
20 import android.app.job.JobParameters;
21 import android.os.PowerManager;
22 import android.os.PowerManager.OnThermalStatusChangedListener;
23 import android.util.IndentingPrintWriter;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 import com.android.server.job.JobSchedulerService;
27 import com.android.server.job.controllers.JobStatus;
28 
29 public class ThermalStatusRestriction extends JobRestriction {
30     private static final String TAG = "ThermalStatusRestriction";
31 
32     /** The threshold at which we start restricting low and min priority jobs. */
33     private static final int LOW_PRIORITY_THRESHOLD = PowerManager.THERMAL_STATUS_LIGHT;
34     /** The threshold at which we start restricting higher priority jobs. */
35     private static final int HIGHER_PRIORITY_THRESHOLD = PowerManager.THERMAL_STATUS_MODERATE;
36     /** The lowest threshold at which we start restricting jobs. */
37     private static final int LOWER_THRESHOLD = LOW_PRIORITY_THRESHOLD;
38     /** The threshold at which we start restricting ALL jobs. */
39     private static final int UPPER_THRESHOLD = PowerManager.THERMAL_STATUS_SEVERE;
40 
41     private volatile int mThermalStatus = PowerManager.THERMAL_STATUS_NONE;
42 
ThermalStatusRestriction(JobSchedulerService service)43     public ThermalStatusRestriction(JobSchedulerService service) {
44         super(service, JobParameters.STOP_REASON_DEVICE_STATE,
45                 JobParameters.INTERNAL_STOP_REASON_DEVICE_THERMAL);
46     }
47 
48     @Override
onSystemServicesReady()49     public void onSystemServicesReady() {
50         final PowerManager powerManager =
51                 mService.getTestableContext().getSystemService(PowerManager.class);
52         // Use MainExecutor
53         powerManager.addThermalStatusListener(new OnThermalStatusChangedListener() {
54             @Override
55             public void onThermalStatusChanged(int status) {
56                 // This is called on the main thread. Do not do any slow operations in it.
57                 // mService.onControllerStateChanged() will just post a message, which is okay.
58 
59                 // There are three buckets:
60                 //   1. Below the lower threshold (we don't care about changes within this bucket)
61                 //   2. Between the lower and upper thresholds.
62                 //     -> We care about transitions across buckets
63                 //     -> We care about transitions within the middle bucket
64                 //   3. Upper the upper threshold (we don't care about changes within this bucket)
65                 final boolean significantChange =
66                         // Handle transitions within and into the bucket we care about (thus
67                         // causing us to change our restrictions).
68                         (status >= LOWER_THRESHOLD && status <= UPPER_THRESHOLD)
69                                 // Take care of transitions from the 2nd or 3rd bucket to the 1st
70                                 // bucket (thus exiting any restrictions we started enforcing).
71                                 || (mThermalStatus >= LOWER_THRESHOLD && status < LOWER_THRESHOLD)
72                                 // Take care of transitions from the 1st or 2nd bucket to the 3rd
73                                 // bucket (thus resulting in us beginning to enforce the tightest
74                                 // restrictions).
75                                 || (mThermalStatus < UPPER_THRESHOLD && status > UPPER_THRESHOLD);
76                 mThermalStatus = status;
77                 if (significantChange) {
78                     mService.onControllerStateChanged(null);
79                 }
80             }
81         });
82     }
83 
84     @Override
isJobRestricted(JobStatus job)85     public boolean isJobRestricted(JobStatus job) {
86         if (mThermalStatus >= UPPER_THRESHOLD) {
87             return true;
88         }
89         final int priority = job.getEffectivePriority();
90         if (mThermalStatus >= HIGHER_PRIORITY_THRESHOLD) {
91             // For moderate throttling, only let expedited jobs and high priority regular jobs that
92             // are already running run.
93             return !job.shouldTreatAsExpeditedJob()
94                     && !(priority == JobInfo.PRIORITY_HIGH
95                     && mService.isCurrentlyRunningLocked(job));
96         }
97         if (mThermalStatus >= LOW_PRIORITY_THRESHOLD) {
98             // For light throttling, throttle all min priority jobs and all low priority jobs that
99             // aren't already running.
100             return (priority == JobInfo.PRIORITY_LOW && !mService.isCurrentlyRunningLocked(job))
101                     || priority == JobInfo.PRIORITY_MIN;
102         }
103         return false;
104     }
105 
106     @VisibleForTesting
getThermalStatus()107     int getThermalStatus() {
108         return mThermalStatus;
109     }
110 
111     @Override
dumpConstants(IndentingPrintWriter pw)112     public void dumpConstants(IndentingPrintWriter pw) {
113         pw.print("Thermal status: ");
114         pw.println(mThermalStatus);
115     }
116 }
117