1/**
2 * Copyright (C) 2009 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
17package com.android.internal.util;
18
19import android.os.Message;
20
21import java.util.Vector;
22
23/**
24 * {@hide}
25 *
26 * A list of messages recently processed by the state machine.
27 *
28 * The class maintains a list of messages that have been most
29 * recently processed. The list is finite and may be set in the
30 * constructor or by calling setSize. The public interface also
31 * includes size which returns the number of recent messages,
32 * count which is the number of message processed since the
33 * the last setSize, get which returns a processed message and
34 * add which adds a processed messaged.
35 */
36public class ProcessedMessages {
37
38    public static final int DEFAULT_SIZE = 20;
39
40    /**
41     * The information maintained for a processed message.
42     */
43    public class Info {
44        private int what;
45        private HierarchicalState state;
46        private HierarchicalState orgState;
47
48        /**
49         * Constructor
50         * @param message
51         * @param state that handled the message
52         * @param orgState is the first state the received the message but
53         * did not processes the message.
54         */
55        Info(Message message, HierarchicalState state, HierarchicalState orgState) {
56            update(message, state, orgState);
57        }
58
59        /**
60         * Update the information in the record.
61         * @param state that handled the message
62         * @param orgState is the first state the received the message but
63         * did not processes the message.
64         */
65        public void update(Message message, HierarchicalState state, HierarchicalState orgState) {
66            this.what = message.what;
67            this.state = state;
68            this.orgState = orgState;
69        }
70
71        /**
72         * @return the command that was executing
73         */
74        public int getWhat() {
75            return what;
76        }
77
78        /**
79         * @return the state that handled this message
80         */
81        public HierarchicalState getState() {
82            return state;
83        }
84
85        /**
86         * @return the original state that received the message.
87         */
88        public HierarchicalState getOriginalState() {
89            return orgState;
90        }
91
92        /**
93         * @return as string
94         */
95        public String toString() {
96            StringBuilder sb = new StringBuilder();
97            sb.append("what=");
98            sb.append(what);
99            sb.append(" state=");
100            sb.append(cn(state));
101            sb.append(" orgState=");
102            sb.append(cn(orgState));
103            return sb.toString();
104        }
105
106        /**
107         * @return an objects class name
108         */
109        private String cn(Object n) {
110            if (n == null) {
111                return "null";
112            } else {
113                String name = n.getClass().getName();
114                int lastDollar = name.lastIndexOf('$');
115                return name.substring(lastDollar + 1);
116            }
117        }
118    }
119
120    private Vector<Info> mMessages = new Vector<Info>();
121    private int mMaxSize = DEFAULT_SIZE;
122    private int mOldestIndex = 0;
123    private int mCount = 0;
124
125    /**
126     * Constructor
127     */
128    ProcessedMessages() {
129    }
130
131    ProcessedMessages(int maxSize) {
132        setSize(maxSize);
133    }
134
135    /**
136     * Set size of messages to maintain and clears all current messages.
137     *
138     * @param maxSize number of messages to maintain at anyone time.
139    */
140    void setSize(int maxSize) {
141        mMaxSize = maxSize;
142        mCount = 0;
143        mMessages.clear();
144    }
145
146    /**
147     * @return the number of recent messages.
148     */
149    int size() {
150        return mMessages.size();
151    }
152
153    /**
154     * @return the total number of messages processed since size was set.
155     */
156    int count() {
157        return mCount;
158    }
159
160    /**
161     * @return the information on a particular record. 0 is the oldest
162     * record and size()-1 is the newest record. If the index is to
163     * large null is returned.
164     */
165    Info get(int index) {
166        int nextIndex = mOldestIndex + index;
167        if (nextIndex >= mMaxSize) {
168            nextIndex -= mMaxSize;
169        }
170        if (nextIndex >= size()) {
171            return null;
172        } else {
173            return mMessages.get(nextIndex);
174        }
175    }
176
177    /**
178     * Add a processed message.
179     *
180     * @param message
181     * @param state that handled the message
182     * @param orgState is the first state the received the message but
183     * did not processes the message.
184     */
185    void add(Message message, HierarchicalState state, HierarchicalState orgState) {
186        mCount += 1;
187        if (mMessages.size() < mMaxSize) {
188            mMessages.add(new Info(message, state, orgState));
189        } else {
190            Info info = mMessages.get(mOldestIndex);
191            mOldestIndex += 1;
192            if (mOldestIndex >= mMaxSize) {
193                mOldestIndex = 0;
194            }
195            info.update(message, state, orgState);
196        }
197    }
198}
199