blob: 9b727f8731cea54ea804d49560643b2b02feaf51 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.car.os;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.car.Car;
import android.car.CarManagerBase;
import android.car.annotation.AddedInOrBefore;
import android.car.annotation.ApiRequirements;
import android.car.annotation.ApiRequirements.CarVersion;
import android.car.annotation.ApiRequirements.PlatformVersion;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
* CarPerformanceManager allows applications to tweak performance settings for their
* processes/threads and listen for CPU available change notifications.
*
* @hide
*/
@SystemApi
public final class CarPerformanceManager extends CarManagerBase {
private final ICarPerformanceService mService;
/**
* An exception type thrown when {@link setThreadPriority} failed.
*
* @hide
*/
@SystemApi
@ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_1,
minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_1)
public static final class SetSchedulerFailedException extends Exception {
SetSchedulerFailedException(Throwable cause) {
super(cause);
}
}
/** @hide */
public CarPerformanceManager(Car car, IBinder service) {
super(car);
mService = ICarPerformanceService.Stub.asInterface(service);
}
/** @hide */
@Override
@AddedInOrBefore(majorVersion = 33)
public void onCarDisconnected() {
// nothing to do
}
/**
* Listener to get CPU availability change notifications.
*
* <p>
* Applications implement the listener method to perform one of the following actions:
* <ul>
* <li>Execute CPU intensive tasks when the CPU availability percent is above the specified
* upper bound percent.
* <li>Stop executing CPU intensive tasks when the CPU availability percent is below
* the specified lower bound percent.
* <li>Handle the CPU availability timeout.
* </ul>
* </p>
*
* @hide
*/
public interface CpuAvailabilityChangeListener {
/**
* Called on one of the following events:
* 1. When the CPU availability percent has reached or decreased below the lower bound
* percent specified at {@link CpuAvailabilityMonitoringConfig#getLowerBoundPercent()}.
* 2. When the CPU availability percent has reached or increased above the upper bound
* percent specified at {@link CpuAvailabilityMonitoringConfig#getUpperBoundPercent()}.
* 3. When the CPU availability monitoring has reached the timeout specified at
* {@link CpuAvailabilityMonitoringConfig#getTimeoutInSeconds()}.
*
* <p>The listener is called at the executor which is specified in
* {@link CarPerformanceManager#addCpuAvailabilityChangeListener(Executor,
* CpuAvailabilityMonitoringConfig, CpuAvailabilityChangeListener)}.
*
* @param info CPU availability information.
*/
@AddedInOrBefore(majorVersion = 33)
void onCpuAvailabilityChange(@NonNull CpuAvailabilityInfo info);
}
/**
* Adds the {@link CpuAvailabilityChangeListener} for the calling package.
*
* @param config CPU availability monitoring config.
* @param listener Listener implementing {@link CpuAvailabilityChangeListener}
* interface.
*
* @throws IllegalStateException if {@code listener} is already added.
*
* @hide
*/
@RequiresPermission(Car.PERMISSION_COLLECT_CAR_CPU_INFO)
@AddedInOrBefore(majorVersion = 33)
public void addCpuAvailabilityChangeListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull CpuAvailabilityMonitoringConfig config,
@NonNull CpuAvailabilityChangeListener listener) {
Objects.requireNonNull(executor, "Executor must be non-null");
Objects.requireNonNull(config, "Config must be non-null");
Objects.requireNonNull(listener, "Listener must be non-null");
// TODO(b/217422127): Implement the API.
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Removes the {@link CpuAvailabilityChangeListener} for the calling package.
*
* @param listener Listener implementing {@link CpuAvailabilityChangeListener}
* interface.
*
* @hide
*/
@RequiresPermission(Car.PERMISSION_COLLECT_CAR_CPU_INFO)
@AddedInOrBefore(majorVersion = 33)
public void removeCpuAvailabilityChangeListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull CpuAvailabilityChangeListener listener) {
Objects.requireNonNull(executor, "Executor must be non-null");
Objects.requireNonNull(listener, "Listener must be non-null");
// TODO(b/217422127): Implement the API.
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Sets the thread scheduling policy with priority for the current thread.
*
* For {@link ThreadPolicyWithPriority#SCHED_DEFAULT} scheduling algorithm, the standard
* round-robin time-sharing algorithm will be used and the priority field will be ignored.
* Please use {@link Process#setThreadPriority} to adjust the priority for the default
* scheduling.
*
* @param policyWithPriority A thread scheduling policy with priority.
* @throws IllegalArgumentException If the policy is not supported or the priority is not within
* {@link ThreadPolicyWithPriority#PRIORITY_MIN} and
* {@link ThreadPolicyWithPriority#PRIORITY_MAX}.
* @throws SetSchedulerFailedException If failed to set the scheduling policy and priority.
* @throws SecurityException If permission check failed.
*
* @hide
*/
@SystemApi
@ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
minPlatformVersion = PlatformVersion.TIRAMISU_1)
@RequiresPermission(Car.PERMISSION_MANAGE_THREAD_PRIORITY)
public void setThreadPriority(@NonNull ThreadPolicyWithPriority policyWithPriority)
throws SetSchedulerFailedException {
int tid = Process.myTid();
try {
mService.setThreadPriority(tid, policyWithPriority);
} catch (ServiceSpecificException e) {
throw new SetSchedulerFailedException(e);
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
}
}
/**
* Gets the thread scheduling policy with priority for the current thread.
*
* For {@link ThreadPolicyWithPriority#SCHED_FIFO} or
* {@link ThreadPolicyWithPriority#SCHED_RR}, this function returns the priority for the
* scheduling algorithm. For {@link ThreadPolicyWithPriority#SCHED_DEFAULT} which is the
* standard round-robin time-sharing algorithm, this function always return 0 for priority. The
* priority for the default algorithm can be fetched by {@link Process#getThreadPriority}.
*
* @throws IllegalStateException If failed to get policy or priority.
* @throws SecurityException If permission check failed.
*
* @hide
*/
@SystemApi
@ApiRequirements(minCarVersion = CarVersion.TIRAMISU_1,
minPlatformVersion = PlatformVersion.TIRAMISU_1)
@RequiresPermission(Car.PERMISSION_MANAGE_THREAD_PRIORITY)
public @NonNull ThreadPolicyWithPriority getThreadPriority() {
int tid = Process.myTid();
try {
return mService.getThreadPriority(tid);
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
// Car service has crashed, return a default value since we do not
// want to crash the client.
return new ThreadPolicyWithPriority(
ThreadPolicyWithPriority.SCHED_DEFAULT, /* priority= */ 0);
}
}
}