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