1 /* 2 * Copyright (C) 2022 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.car.os; 18 19 import android.annotation.CallbackExecutor; 20 import android.annotation.NonNull; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemApi; 23 import android.car.Car; 24 import android.car.CarManagerBase; 25 import android.os.IBinder; 26 import android.os.Process; 27 import android.os.RemoteException; 28 import android.os.ServiceSpecificException; 29 30 import java.util.Objects; 31 import java.util.concurrent.Executor; 32 33 /** 34 * CarPerformanceManager allows applications to tweak performance settings for their 35 * processes/threads and listen for CPU available change notifications. 36 * 37 * @hide 38 */ 39 @SystemApi 40 public final class CarPerformanceManager extends CarManagerBase { 41 42 private final ICarPerformanceService mService; 43 44 /** 45 * An exception type thrown when {@link setThreadPriority} failed. 46 * 47 * @hide 48 */ 49 @SystemApi 50 public static final class SetSchedulerFailedException extends Exception { SetSchedulerFailedException(Throwable cause)51 SetSchedulerFailedException(Throwable cause) { 52 super(cause); 53 } 54 } 55 56 /** @hide */ CarPerformanceManager(Car car, IBinder service)57 public CarPerformanceManager(Car car, IBinder service) { 58 super(car); 59 mService = ICarPerformanceService.Stub.asInterface(service); 60 } 61 62 /** @hide */ 63 @Override onCarDisconnected()64 public void onCarDisconnected() { 65 // nothing to do 66 } 67 68 /** 69 * Listener to get CPU availability change notifications. 70 * 71 * <p> 72 * Applications implement the listener method to perform one of the following actions: 73 * <ul> 74 * <li>Execute CPU intensive tasks when the CPU availability percent is above the specified 75 * upper bound percent. 76 * <li>Stop executing CPU intensive tasks when the CPU availability percent is below 77 * the specified lower bound percent. 78 * <li>Handle the CPU availability timeout. 79 * </ul> 80 * </p> 81 * 82 * @hide 83 * @removed API not used since Android U. Must be removed in Android W (release 35). 84 */ 85 public interface CpuAvailabilityChangeListener { 86 /** 87 * Called on one of the following events: 88 * 1. When the CPU availability percent has reached or decreased below the lower bound 89 * percent specified at {@link CpuAvailabilityMonitoringConfig#getLowerBoundPercent()}. 90 * 2. When the CPU availability percent has reached or increased above the upper bound 91 * percent specified at {@link CpuAvailabilityMonitoringConfig#getUpperBoundPercent()}. 92 * 3. When the CPU availability monitoring has reached the timeout specified at 93 * {@link CpuAvailabilityMonitoringConfig#getTimeoutInSeconds()}. 94 * 95 * <p>The listener is called at the executor which is specified in 96 * {@link CarPerformanceManager#addCpuAvailabilityChangeListener(Executor, 97 * CpuAvailabilityMonitoringConfig, CpuAvailabilityChangeListener)}. 98 * 99 * @param info CPU availability information. 100 */ onCpuAvailabilityChange(@onNull CpuAvailabilityInfo info)101 void onCpuAvailabilityChange(@NonNull CpuAvailabilityInfo info); 102 } 103 104 /** 105 * Adds the {@link CpuAvailabilityChangeListener} for the calling package. 106 * 107 * @param config CPU availability monitoring config. 108 * @param listener Listener implementing {@link CpuAvailabilityChangeListener} 109 * interface. 110 * 111 * @throws IllegalStateException if {@code listener} is already added. 112 * 113 * @hide 114 * @removed API not used since Android U. Must be removed in Android W (release 35). 115 */ 116 @RequiresPermission(Car.PERMISSION_COLLECT_CAR_CPU_INFO) addCpuAvailabilityChangeListener( @onNull @allbackExecutor Executor executor, @NonNull CpuAvailabilityMonitoringConfig config, @NonNull CpuAvailabilityChangeListener listener)117 public void addCpuAvailabilityChangeListener( 118 @NonNull @CallbackExecutor Executor executor, 119 @NonNull CpuAvailabilityMonitoringConfig config, 120 @NonNull CpuAvailabilityChangeListener listener) { 121 Objects.requireNonNull(executor, "Executor must be non-null"); 122 Objects.requireNonNull(config, "Config must be non-null"); 123 Objects.requireNonNull(listener, "Listener must be non-null"); 124 125 // TODO(b/217422127): Implement the API. 126 throw new UnsupportedOperationException("Not yet implemented"); 127 } 128 129 /** 130 * Removes the {@link CpuAvailabilityChangeListener} for the calling package. 131 * 132 * @param listener Listener implementing {@link CpuAvailabilityChangeListener} 133 * interface. 134 * 135 * @hide 136 * @removed API not used since Android U. Must be removed in Android W (release 35). 137 */ 138 @RequiresPermission(Car.PERMISSION_COLLECT_CAR_CPU_INFO) removeCpuAvailabilityChangeListener( @onNull @allbackExecutor Executor executor, @NonNull CpuAvailabilityChangeListener listener)139 public void removeCpuAvailabilityChangeListener( 140 @NonNull @CallbackExecutor Executor executor, 141 @NonNull CpuAvailabilityChangeListener listener) { 142 Objects.requireNonNull(executor, "Executor must be non-null"); 143 Objects.requireNonNull(listener, "Listener must be non-null"); 144 145 // TODO(b/217422127): Implement the API. 146 throw new UnsupportedOperationException("Not yet implemented"); 147 } 148 149 /** 150 * Sets the thread scheduling policy with priority for the current thread. 151 * 152 * For {@link ThreadPolicyWithPriority#SCHED_DEFAULT} scheduling algorithm, the standard 153 * round-robin time-sharing algorithm will be used and the priority field will be ignored. 154 * Please use {@link Process#setThreadPriority} to adjust the priority for the default 155 * scheduling. 156 * 157 * @param policyWithPriority A thread scheduling policy with priority. 158 * @throws IllegalArgumentException If the policy is not supported or the priority is not within 159 * {@link ThreadPolicyWithPriority#PRIORITY_MIN} and 160 * {@link ThreadPolicyWithPriority#PRIORITY_MAX}. 161 * @throws SetSchedulerFailedException If failed to set the scheduling policy and priority. 162 * @throws SecurityException If permission check failed. 163 * 164 * @hide 165 */ 166 @SystemApi 167 @RequiresPermission(Car.PERMISSION_MANAGE_THREAD_PRIORITY) setThreadPriority(@onNull ThreadPolicyWithPriority policyWithPriority)168 public void setThreadPriority(@NonNull ThreadPolicyWithPriority policyWithPriority) 169 throws SetSchedulerFailedException { 170 int tid = Process.myTid(); 171 try { 172 mService.setThreadPriority(tid, policyWithPriority); 173 } catch (ServiceSpecificException e) { 174 throw new SetSchedulerFailedException(e); 175 } catch (RemoteException e) { 176 handleRemoteExceptionFromCarService(e); 177 } 178 } 179 180 /** 181 * Gets the thread scheduling policy with priority for the current thread. 182 * 183 * For {@link ThreadPolicyWithPriority#SCHED_FIFO} or 184 * {@link ThreadPolicyWithPriority#SCHED_RR}, this function returns the priority for the 185 * scheduling algorithm. For {@link ThreadPolicyWithPriority#SCHED_DEFAULT} which is the 186 * standard round-robin time-sharing algorithm, this function always return 0 for priority. The 187 * priority for the default algorithm can be fetched by {@link Process#getThreadPriority}. 188 * 189 * @throws IllegalStateException If failed to get policy or priority. 190 * @throws SecurityException If permission check failed. 191 * 192 * @hide 193 */ 194 @SystemApi 195 @RequiresPermission(Car.PERMISSION_MANAGE_THREAD_PRIORITY) getThreadPriority()196 public @NonNull ThreadPolicyWithPriority getThreadPriority() { 197 int tid = Process.myTid(); 198 try { 199 return mService.getThreadPriority(tid); 200 } catch (RemoteException e) { 201 handleRemoteExceptionFromCarService(e); 202 // Car service has crashed, return a default value since we do not 203 // want to crash the client. 204 return new ThreadPolicyWithPriority( 205 ThreadPolicyWithPriority.SCHED_DEFAULT, /* priority= */ 0); 206 } 207 } 208 } 209