1 /* 2 * Copyright (C) 2020 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.util; 18 19 import com.android.internal.util.IState; 20 import com.android.internal.util.StateMachine; 21 import com.android.internal.util.StateMachine.LogRec; 22 23 import java.io.FileDescriptor; 24 import java.io.PrintWriter; 25 import java.util.ArrayList; 26 import java.util.List; 27 28 /** 29 * Enough information about a StateMachine to reconstruct the dump() log. This is necessary 30 * because a StateMachine's logs are lost upon quitting 31 * ({@link StateMachine#quit()} or {@link StateMachine#quitNow()}). 32 * 33 * Note: most of StateMachine's internal variables (including LogRecs) are stored in the 34 * StateMachine's inner class SmHandler. StateMachine clears its reference to SmHandler 35 * after quitting, thereby losing all the LogRecs as well. 36 */ 37 public class StateMachineObituary { 38 private final String mName; 39 /** 40 * Total records processed, which may be greater than the size of mLogRecs since 41 * messages could be discarded. 42 */ 43 private final int mTotalProcessedRecords; 44 private final List<String> mLogRecs = new ArrayList<>(); 45 private final String mLastStateName; 46 StateMachineObituary(StateMachine stateMachine)47 public StateMachineObituary(StateMachine stateMachine) { 48 mName = stateMachine.getName(); 49 // total number of LogRecs ever 50 mTotalProcessedRecords = stateMachine.getLogRecCount(); 51 // number of records currently readable i.e. not yet discarded 52 int currentReadableRecords = stateMachine.getLogRecSize(); 53 // LogRecs are mutable and StateMachine internally reuses LogRec instances instead of 54 // allocating new ones. Thus, convert the LogRecs to Strings. 55 for (int i = 0; i < currentReadableRecords; i++) { 56 LogRec logRec = stateMachine.getLogRec(i); 57 if (logRec != null) { // just in case 58 mLogRecs.add(logRec.toString()); 59 } 60 } 61 final IState curState = stateMachine.getCurrentState(); 62 mLastStateName = curState == null ? "<QUIT>" : curState.getName(); 63 } 64 65 /** Dump the same information as {@link StateMachine#dump} when the StateMachine was active. */ dump(FileDescriptor fd, PrintWriter pw, String[] args)66 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 67 pw.println(mName + ":"); 68 pw.println(" total records=" + mTotalProcessedRecords); 69 int i = 0; 70 for (String logRec : mLogRecs) { 71 pw.println(" rec[" + i + "]: " + logRec); 72 pw.flush(); 73 i++; 74 } 75 pw.println("curState=" + mLastStateName); 76 } 77 } 78