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