1 /*
2  * Copyright (C) 2021 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.systemui.util.concurrency;
18 
19 /**
20  * Allows triggering methods based on a passed in id or message, generally on another thread.
21  *
22  * Messages sent on to this router must be processed in order. That is to say, if three
23  * messages are sent with no delay, they must be processed in the order they were sent. Moreover,
24  * if messages are sent with various delays, they must be processed in order of their delay.
25  *
26  *  Messages can be passed by either a simple integer or an instance of a class. Unique integers are
27  *  considered unique messages. Unique message classes (not instances) are considered unique
28  *  messages. You can use message classes to pass extra data for processing to subscribers.
29  *
30  *  <pre>
31  *      // Three messages with three unique integer messages.
32  *      // They can be subscribed to independently.
33  *      router.sendMessage(0);
34  *      router.sendMessage(1);
35  *      router.sendMessage(2);
36  *
37  *      // Three messages with two unique message classes.
38  *      // The first and third messages will be delivered to the same subscribers.
39  *      router.sendMessage(new Foo(0));
40  *      router.sendMessage(new Bar(1));
41  *      router.sendMessage(new Foo(2));
42  *  </pre>
43  *
44  * The number of unique ids and message types used should be relatively constrained. Construct
45  * a custom message-class and put unique, per-message data inside of it.
46  */
47 public interface MessageRouter {
48     /**
49      * Alerts any listeners subscribed to the passed in id.
50      *
51      * The number of unique ids used should be relatively constrained - used to identify the type
52      * of message being sent. If unique information needs to be passed with each call, use
53      * {@link #sendMessage(Object)}.
54      *
55      * @param id An identifier for the message
56      */
sendMessage(int id)57     default void sendMessage(int id) {
58         sendMessageDelayed(id, 0);
59     }
60 
61     /**
62      * Alerts any listeners subscribed to the passed in message.
63      *
64      * The number of message types used should be relatively constrained. If no unique information
65      * needs to be passed in, you can simply use {@link #sendMessage(int)}} which takes an integer
66      * instead of a unique class type.
67      *
68      * The class of the passed in object will be used to router the message.
69      *
70      * @param data A message containing extra data for processing.
71      */
sendMessage(Object data)72     default void sendMessage(Object data) {
73         sendMessageDelayed(data, 0);
74     }
75 
76     /**
77      * Alerts any listeners subscribed to the passed in id in the future.
78      *
79      * The number of unique ids used should be relatively constrained - used to identify the type
80      * of message being sent. If unique information needs to be passed with each call, use
81      * {@link #sendMessageDelayed(Object, long)}.
82      *
83      * @param id An identifier for the message
84      * @param delayMs Number of milliseconds to wait before alerting.
85      */
sendMessageDelayed(int id, long delayMs)86     void sendMessageDelayed(int id, long delayMs);
87 
88 
89     /**
90      * Alerts any listeners subscribed to the passed in message in the future.
91      *
92      * The number of message types used should be relatively constrained. If no unique information
93      * needs to be passed in, you can simply use {@link #sendMessageDelayed(int, long)} which takes
94      * an integer instead of a unique class type.
95      *
96      * @param data A message containing extra data for processing.
97      * @param delayMs Number of milliseconds to wait before alerting.
98      */
sendMessageDelayed(Object data, long delayMs)99     void sendMessageDelayed(Object data, long delayMs);
100 
101     /**
102      * Cancel all unprocessed messages for a given id.
103      *
104      * If a message has multiple listeners and one of those listeners has been alerted, the other
105      * listeners that follow it may also be alerted. This is only guaranteed to cancel messages
106      * that are still queued.
107      *
108      * @param id The message id to cancel.
109      */
cancelMessages(int id)110     void cancelMessages(int id);
111 
112     /**
113      * Cancel all unprocessed messages for a given message type.
114      *
115      * If a message has multiple listeners and one of those listeners has been alerted, the other
116      * listeners that follow it may also be alerted. This is only guaranteed to cancel messages
117      * that are still queued.
118      *
119      * @param messageType The class of the message to cancel
120      */
cancelMessages(Class<T> messageType)121     <T> void cancelMessages(Class<T> messageType);
122 
123     /**
124      * Add a listener for a message that does not handle any extra data.
125      *
126      * See also {@link #subscribeTo(Class, DataMessageListener)}.
127      *
128      * @param id The message id to listener for.
129      * @param listener
130      */
subscribeTo(int id, SimpleMessageListener listener)131     void subscribeTo(int id, SimpleMessageListener listener);
132 
133     /**
134      * Add a listener for a message of a specific type.
135      *
136      * See also {@link #subscribeTo(Class, DataMessageListener)}.
137      *
138      * @param messageType The class of message to listen for.
139      * @param listener
140      */
subscribeTo(Class<T> messageType, DataMessageListener<T> listener)141     <T> void subscribeTo(Class<T> messageType, DataMessageListener<T> listener);
142 
143     /**
144      * Remove a listener for a specific message.
145      *
146      * See also {@link #unsubscribeFrom(Class, DataMessageListener)}
147      *
148      * @param id The message id to stop listening for.
149      * @param listener The listener to remove.
150      */
unsubscribeFrom(int id, SimpleMessageListener listener)151     void unsubscribeFrom(int id, SimpleMessageListener listener);
152 
153     /**
154      * Remove a listener for a specific message.
155      *
156      * See also {@link #unsubscribeFrom(int, SimpleMessageListener)}.
157      *
158      * @param messageType The class of message to stop listening for.
159      * @param listener The listener to remove.
160      */
unsubscribeFrom(Class<T> messageType, DataMessageListener<T> listener)161     <T> void unsubscribeFrom(Class<T> messageType, DataMessageListener<T> listener);
162 
163     /**
164      * Remove a listener for all messages that it is subscribed to.
165      *
166      * See also {@link #unsubscribeFrom(DataMessageListener)}.
167      *
168      * @param listener The listener to remove.
169      */
unsubscribeFrom(SimpleMessageListener listener)170     void unsubscribeFrom(SimpleMessageListener listener);
171 
172     /**
173      * Remove a listener for all messages that it is subscribed to.
174      *
175      * See also {@link #unsubscribeFrom(SimpleMessageListener)}.
176      *
177      * @param listener The listener to remove.
178      */
unsubscribeFrom(DataMessageListener<T> listener)179     <T> void unsubscribeFrom(DataMessageListener<T> listener);
180 
181     /**
182      * A Listener interface for when no extra data is expected or desired.
183      */
184     interface SimpleMessageListener {
185         /** */
onMessage(int id)186         void onMessage(int id);
187     }
188 
189     /**
190      * A Listener interface for when extra data is expected or desired.
191      *
192      * @param <T>
193      */
194     interface DataMessageListener<T> {
195         /** */
onMessage(T data)196         void onMessage(T data);
197     }
198 }
199