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