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