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.server.wifi;
18 
19 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_THREAD_TASK_EXECUTED;
20 
21 import android.annotation.NonNull;
22 import android.os.Message;
23 import android.os.Trace;
24 import android.util.LocalLog;
25 
26 import com.android.internal.util.State;
27 import com.android.server.wifi.proto.WifiStatsLog;
28 
29 /**
30  * RunnerState class is a wrapper based on State class to monitor and track the State enter/exit
31  * and message handler execution for taking longer time than the expected threshold.
32  * User must extend the RunnerState class instead of State, and provide the implementation of:
33  * { @link RunnerState#enterImpl() } { @link RunnerState#exitImpl() }
34  * { @link RunnerState#processMessageImpl() }
35  * { @link RunnerState#getMessageLogRec() }
36  *
37  */
38 public abstract class RunnerState extends State {
39     private static final String TAG = "RunnerState";
40     private static final int METRICS_THRESHOLD_MILLIS = 100;
41 
42     /** Message.what value when entering */
43     public static final int STATE_ENTER_CMD = -3;
44 
45     /** Message.what value when exiting */
46     public static final int STATE_EXIT_CMD = -4;
47 
48     private final int mRunningTimeThresholdInMilliseconds;
49     // TODO: b/246623192 Add Wifi metric for Runner state overruns.
50     private final LocalLog mLocalLog;
51 
52     /**
53      * The Runner state Constructor
54      * @param threshold the running time threshold in milliseconds
55      */
RunnerState(int threshold, @NonNull LocalLog localLog)56     public RunnerState(int threshold, @NonNull LocalLog localLog) {
57         mRunningTimeThresholdInMilliseconds = threshold;
58         mLocalLog = localLog;
59     }
60 
61     @Override
processMessage(Message message)62     public boolean processMessage(Message message) {
63         long startTime = System.currentTimeMillis();
64 
65         String signatureToLog = getMessageLogRec(message);
66         if (signatureToLog == null) {
67             signatureToLog = getMessageLogRec(message.what);
68         }
69         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
70         boolean ret = processMessageImpl(message);
71         Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
72         long runTime = System.currentTimeMillis() - startTime;
73         if (runTime > mRunningTimeThresholdInMilliseconds) {
74             mLocalLog.log(signatureToLog + " was running for " + runTime + " ms");
75         }
76         if (runTime > METRICS_THRESHOLD_MILLIS) {
77             WifiStatsLog.write(WIFI_THREAD_TASK_EXECUTED, (int) runTime, 0, signatureToLog);
78         }
79         return ret;
80     }
81 
82     @Override
enter()83     public void enter() {
84         long startTime = System.currentTimeMillis();
85         String signatureToLog = getMessageLogRec(STATE_ENTER_CMD);
86         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
87         enterImpl();
88         Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
89         long runTime = System.currentTimeMillis() - startTime;
90         if (runTime > mRunningTimeThresholdInMilliseconds) {
91             mLocalLog.log(signatureToLog + " was running for " + runTime + " ms");
92         }
93         if (runTime > METRICS_THRESHOLD_MILLIS) {
94             WifiStatsLog.write(WIFI_THREAD_TASK_EXECUTED, (int) runTime, 0, signatureToLog);
95         }
96     }
97 
98     @Override
exit()99     public void exit() {
100         long startTime = System.currentTimeMillis();
101         String signatureToLog = getMessageLogRec(STATE_EXIT_CMD);
102         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
103         exitImpl();
104         Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
105         long runTime = System.currentTimeMillis() - startTime;
106         if (runTime > mRunningTimeThresholdInMilliseconds) {
107             mLocalLog.log(signatureToLog + " was running for " + runTime + " ms");
108         }
109         if (runTime > METRICS_THRESHOLD_MILLIS) {
110             WifiStatsLog.write(WIFI_THREAD_TASK_EXECUTED, (int) runTime, 0, signatureToLog);
111         }
112     }
113 
114     /**
115      * Implement this method for State enter process, instead of enter()
116      */
enterImpl()117     public abstract void enterImpl();
118 
119     /**
120      * Implement this method for State exit process, instead of exit()
121      */
exitImpl()122     public abstract void exitImpl();
123 
124     /**
125      * Implement this method for process message, instead of processMessage()
126      */
processMessageImpl(Message msg)127     public abstract boolean processMessageImpl(Message msg);
128 
129     /**
130      * Implement this to translate a message `what` into a readable String
131      * @param what message 'what' field
132      * @return Readable string
133      */
getMessageLogRec(int what)134     public String getMessageLogRec(int what) {
135         return null;
136     };
137 
138     /**
139      * Implement this to translate a message into a readable String
140      * @return Readable string
141      */
getMessageLogRec(Message message)142     public String getMessageLogRec(Message message) {
143         return null;
144     };
145 }
146