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 com.android.car.os;
18 
19 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
20 
21 import android.car.Car;
22 import android.car.builtin.util.Slogf;
23 import android.car.os.ICarPerformanceService;
24 import android.car.os.ThreadPolicyWithPriority;
25 import android.content.Context;
26 import android.os.Binder;
27 import android.os.RemoteException;
28 import android.util.Log;
29 import android.util.proto.ProtoOutputStream;
30 
31 import com.android.car.CarLocalServices;
32 import com.android.car.CarLog;
33 import com.android.car.CarServiceBase;
34 import com.android.car.CarServiceUtils;
35 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
36 import com.android.car.internal.util.IndentingPrintWriter;
37 import com.android.car.watchdog.CarWatchdogService;
38 
39 /**
40  * Service to implement CarPerformanceManager API.
41  */
42 public final class CarPerformanceService extends ICarPerformanceService.Stub
43         implements CarServiceBase {
44     static final String TAG = CarLog.tagFor(CarPerformanceService.class);
45 
46     private static final boolean DEBUG = Slogf.isLoggable(TAG, Log.DEBUG);
47 
48     private CarWatchdogService mCarWatchdogService;
49     private final Context mContext;
50 
CarPerformanceService(Context context)51     public CarPerformanceService(Context context) {
52         mContext = context;
53     }
54 
55     @Override
init()56     public void init() {
57         mCarWatchdogService = CarLocalServices.getService(CarWatchdogService.class);
58         if (DEBUG) {
59             Slogf.d(TAG, "CarPerformanceService is initialized");
60         }
61     }
62 
63     @Override
release()64     public void release() {}
65 
66     @Override
67     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dump(IndentingPrintWriter writer)68     public void dump(IndentingPrintWriter writer) {
69         writer.printf("*%s*\n", getClass().getSimpleName());
70         writer.increaseIndent();
71         writer.printf("DEBUG=%s", DEBUG);
72         writer.decreaseIndent();
73     }
74 
75     @Override
76     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dumpProto(ProtoOutputStream proto)77     public void dumpProto(ProtoOutputStream proto) {}
78 
79     /**
80      * Sets the thread priority for a specific thread.
81      *
82      * The thread must belong to the calling process.
83      *
84      * @throws IllegalArgumentException If the given policy/priority is not valid.
85      * @throws IllegalStateException If the provided tid does not belong to the calling process.
86      * @throws RemoteException If binder error happens.
87      * @throws SecurityException If permission check failed.
88      * @throws ServiceSpecificException If the operation failed.
89      * @throws UnsupportedOperationException If the current android release doesn't support the API.
90      */
91     @Override
setThreadPriority(int tid, ThreadPolicyWithPriority threadPolicyWithPriority)92     public void setThreadPriority(int tid, ThreadPolicyWithPriority threadPolicyWithPriority)
93             throws RemoteException {
94         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_MANAGE_THREAD_PRIORITY);
95 
96         int pid = Binder.getCallingPid();
97         int uid = Binder.getCallingUid();
98         mCarWatchdogService.setThreadPriority(pid, tid, uid, threadPolicyWithPriority.getPolicy(),
99                 threadPolicyWithPriority.getPriority());
100     }
101 
102     /**
103      * Gets the thread scheduling policy and priority for the specified thread.
104      *
105      * The thread must belong to the calling process.
106      *
107      * @throws IllegalStateException If the operation failed or the provided tid does not belong to
108      *         the calling process.
109      * @throws RemoteException If binder error happens.
110      * @throws SecurityException If permission check failed.
111      * @throws UnsupportedOperationException If the current android release doesn't support the API.
112      */
113     @Override
getThreadPriority(int tid)114     public ThreadPolicyWithPriority getThreadPriority(int tid) throws RemoteException {
115         CarServiceUtils.assertPermission(mContext, Car.PERMISSION_MANAGE_THREAD_PRIORITY);
116 
117         int pid = Binder.getCallingPid();
118         int uid = Binder.getCallingUid();
119         try {
120             int[] result = mCarWatchdogService.getThreadPriority(pid, tid, uid);
121             return new ThreadPolicyWithPriority(result[0], result[1]);
122         } catch (IllegalArgumentException e) {
123             throw new IllegalStateException(
124                     "current scheduling policy doesn't support getting priority, cause: "
125                     + e.getCause(), e);
126         }
127     }
128 }
129