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.google.android.car.kitchensink.os;
18 
19 import static android.car.PlatformVersion.VERSION_CODES.TIRAMISU_1;
20 import static android.car.os.ThreadPolicyWithPriority.priorityToString;
21 import static android.car.os.ThreadPolicyWithPriority.schedToString;
22 
23 import android.car.Car;
24 import android.car.os.CarPerformanceManager;
25 import android.car.os.ThreadPolicyWithPriority;
26 import android.os.Bundle;
27 import android.os.Handler;
28 import android.os.Process;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.ArrayAdapter;
33 import android.widget.Button;
34 import android.widget.EditText;
35 import android.widget.Spinner;
36 import android.widget.TextView;
37 
38 import androidx.fragment.app.Fragment;
39 
40 import com.android.internal.os.BackgroundThread;
41 
42 import com.google.android.car.kitchensink.KitchenSinkActivity;
43 import com.google.android.car.kitchensink.R;
44 
45 public final class CarPerformanceTestFragment extends Fragment {
46     private CarPerformanceManager mCarPerformanceManager;
47     private TextView mTextView;
48     private Spinner mThreadPolicySelect;
49     private EditText mThreadPriorityInput;
50     private static final String NOT_SUPPORTED_MESSAGE =
51             " is not supported on this platform, supported from TM-QPR-1 or up";
52 
53     @Override
onCreate(Bundle savedInstanceState)54     public void onCreate(Bundle savedInstanceState) {
55         Runnable r = () ->
56                 mCarPerformanceManager = ((KitchenSinkActivity) getActivity())
57                         .getPerformanceManager();
58         ((KitchenSinkActivity) getActivity()).requestRefreshManager(r,
59                 new Handler(getContext().getMainLooper()));
60         super.onCreate(savedInstanceState);
61     }
62 
63     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)64     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
65         View v = inflater.inflate(R.layout.car_performance_test, container,
66                 /* attachToRoot= */ false);
67 
68         mTextView = v.findViewById(R.id.thread_priority_textview);
69 
70         Button b = v.findViewById(R.id.get_thread_priority_btn);
71         b.setOnClickListener(this::getThreadPriority);
72 
73         b = v.findViewById(R.id.set_thread_priority_btn);
74         b.setOnClickListener(this::setThreadPriority);
75 
76         mThreadPolicySelect = v.findViewById(R.id.policy_input);
77         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(),
78                 R.array.thread_policy_list, android.R.layout.simple_spinner_item);
79         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
80         mThreadPolicySelect.setAdapter(adapter);
81 
82         mThreadPriorityInput = v.findViewById(R.id.priority_input);
83 
84         int pid = Process.myPid();
85         ((TextView) v.findViewById(R.id.pid_value)).setText(Integer.toString(pid));
86         ((TextView) v.findViewById(R.id.uid_value)).setText(Integer.toString(Process.myUid()));
87         ((TextView) v.findViewById(R.id.process_group_value)).setText(Integer.toString(
88                 Process.getProcessGroup(pid)));
89         int bgThreadTid = BackgroundThread.get().getThreadId();
90         ((TextView) v.findViewById(R.id.bg_thread_process_group_value)).setText(Integer.toString(
91                 Process.getProcessGroup(bgThreadTid)));
92 
93         return v;
94     }
95 
getThreadPriority(View v)96     private void getThreadPriority(View v) {
97         if (!Car.getPlatformVersion().isAtLeast(TIRAMISU_1)) {
98             mTextView.setText("CarPerformanceManager.getThreadPriority"
99                     + NOT_SUPPORTED_MESSAGE);
100             return;
101         }
102 
103         try {
104             ThreadPolicyWithPriority p = mCarPerformanceManager.getThreadPriority();
105 
106             mTextView.setText("Current thread scheduling policy: " + schedToString(p.getPolicy())
107                     + "\nCurrent thread scheduling priority: " + priorityToString(p.getPriority()));
108         } catch (Exception e) {
109             mTextView.setText("Failed to get thread priority, error: " + e);
110         }
111     }
112 
setThreadPriority(View v)113     private void setThreadPriority(View v) {
114         if (!Car.getPlatformVersion().isAtLeast(TIRAMISU_1)) {
115             mTextView.setText("CarPerformanceManager.setThreadPriority"
116                     + NOT_SUPPORTED_MESSAGE);
117             return;
118         }
119 
120         int policyPos = mThreadPolicySelect.getSelectedItemPosition();
121         int policy;
122         switch (policyPos) {
123             case 1:
124                 policy = ThreadPolicyWithPriority.SCHED_FIFO;
125                 break;
126             case 2:
127                 policy = ThreadPolicyWithPriority.SCHED_RR;
128                 break;
129             default:
130                 policy = ThreadPolicyWithPriority.SCHED_DEFAULT;
131                 break;
132         }
133 
134         int priority;
135         try {
136             priority = Integer.parseInt(mThreadPriorityInput.getText().toString());
137         } catch (Exception e) {
138             mTextView.setText("Thread priority must be an integer");
139             return;
140         }
141         try {
142             mCarPerformanceManager.setThreadPriority(
143                     new ThreadPolicyWithPriority(policy, priority));
144         } catch (Exception e) {
145             mTextView.setText("Failed to set thread priority, error: " + e);
146             return;
147         }
148         mTextView.setText("Setting thread priority succeeded");
149     }
150 }
151