1e6c9073d81822496c038e70361e25b3f1287c2bcWinson/*
2e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Copyright (C) 2014 The Android Open Source Project
3e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
4e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Licensed under the Apache License, Version 2.0 (the "License");
5e6c9073d81822496c038e70361e25b3f1287c2bcWinson * you may not use this file except in compliance with the License.
6e6c9073d81822496c038e70361e25b3f1287c2bcWinson * You may obtain a copy of the License at
7e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
8e6c9073d81822496c038e70361e25b3f1287c2bcWinson *      http://www.apache.org/licenses/LICENSE-2.0
9e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
10e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Unless required by applicable law or agreed to in writing, software
11e6c9073d81822496c038e70361e25b3f1287c2bcWinson * distributed under the License is distributed on an "AS IS" BASIS,
12e6c9073d81822496c038e70361e25b3f1287c2bcWinson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e6c9073d81822496c038e70361e25b3f1287c2bcWinson * See the License for the specific language governing permissions and
14e6c9073d81822496c038e70361e25b3f1287c2bcWinson * limitations under the License.
15e6c9073d81822496c038e70361e25b3f1287c2bcWinson */
16e6c9073d81822496c038e70361e25b3f1287c2bcWinson
17e6c9073d81822496c038e70361e25b3f1287c2bcWinsonpackage com.android.systemui.recents.events;
18e6c9073d81822496c038e70361e25b3f1287c2bcWinson
19e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.content.BroadcastReceiver;
20e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.content.Context;
21e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.content.Intent;
22e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.content.IntentFilter;
23e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.os.Bundle;
24e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.os.Handler;
25e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.os.Looper;
26e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.os.SystemClock;
27e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.os.UserHandle;
28e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.util.Log;
29e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport android.util.MutableBoolean;
30c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson
31aaeaac17831090594e4927b1531c4658d239a3eaWinson Chungimport com.android.systemui.recents.misc.ReferenceCountedTrigger;
32aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
33d72c315d5eed3a684eee303364b97129cb821689Winsonimport java.io.PrintWriter;
34e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.lang.ref.WeakReference;
35e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.lang.reflect.Constructor;
36e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.lang.reflect.InvocationTargetException;
37e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.lang.reflect.Method;
38e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.lang.reflect.Modifier;
39e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.util.ArrayList;
40e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.util.Collections;
41e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.util.Comparator;
42e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.util.HashMap;
43e6c9073d81822496c038e70361e25b3f1287c2bcWinsonimport java.util.List;
44e6c9073d81822496c038e70361e25b3f1287c2bcWinson
45e6c9073d81822496c038e70361e25b3f1287c2bcWinson/**
46e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Represents a subscriber, which implements various event bus handler methods.
47e6c9073d81822496c038e70361e25b3f1287c2bcWinson */
48e6c9073d81822496c038e70361e25b3f1287c2bcWinsonclass Subscriber {
49e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private WeakReference<Object> mSubscriber;
50e6c9073d81822496c038e70361e25b3f1287c2bcWinson
51e6c9073d81822496c038e70361e25b3f1287c2bcWinson    long registrationTime;
52e6c9073d81822496c038e70361e25b3f1287c2bcWinson
53e6c9073d81822496c038e70361e25b3f1287c2bcWinson    Subscriber(Object subscriber, long registrationTime) {
54e6c9073d81822496c038e70361e25b3f1287c2bcWinson        mSubscriber = new WeakReference<>(subscriber);
55e6c9073d81822496c038e70361e25b3f1287c2bcWinson        this.registrationTime = registrationTime;
56e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
57e6c9073d81822496c038e70361e25b3f1287c2bcWinson
58e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public String toString(int priority) {
59e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Object sub = mSubscriber.get();
60e6c9073d81822496c038e70361e25b3f1287c2bcWinson        String id = Integer.toHexString(System.identityHashCode(sub));
61e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return sub.getClass().getSimpleName() + " [0x" + id + ", P" + priority + "]";
62e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
63e6c9073d81822496c038e70361e25b3f1287c2bcWinson
64e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public Object getReference() {
65e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return mSubscriber.get();
66e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
67e6c9073d81822496c038e70361e25b3f1287c2bcWinson}
68e6c9073d81822496c038e70361e25b3f1287c2bcWinson
69e6c9073d81822496c038e70361e25b3f1287c2bcWinson/**
70e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Represents an event handler with a priority.
71e6c9073d81822496c038e70361e25b3f1287c2bcWinson */
72e6c9073d81822496c038e70361e25b3f1287c2bcWinsonclass EventHandler {
73e6c9073d81822496c038e70361e25b3f1287c2bcWinson    int priority;
74e6c9073d81822496c038e70361e25b3f1287c2bcWinson    Subscriber subscriber;
75e6c9073d81822496c038e70361e25b3f1287c2bcWinson    EventHandlerMethod method;
76e6c9073d81822496c038e70361e25b3f1287c2bcWinson
77e6c9073d81822496c038e70361e25b3f1287c2bcWinson    EventHandler(Subscriber subscriber, EventHandlerMethod method, int priority) {
78e6c9073d81822496c038e70361e25b3f1287c2bcWinson        this.subscriber = subscriber;
79e6c9073d81822496c038e70361e25b3f1287c2bcWinson        this.method = method;
80e6c9073d81822496c038e70361e25b3f1287c2bcWinson        this.priority = priority;
81e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
82e6c9073d81822496c038e70361e25b3f1287c2bcWinson
83e6c9073d81822496c038e70361e25b3f1287c2bcWinson    @Override
84e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public String toString() {
85e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return subscriber.toString(priority) + " " + method.toString();
86e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
87e6c9073d81822496c038e70361e25b3f1287c2bcWinson}
88e6c9073d81822496c038e70361e25b3f1287c2bcWinson
89e6c9073d81822496c038e70361e25b3f1287c2bcWinson/**
90e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Represents the low level method handling a particular event.
91e6c9073d81822496c038e70361e25b3f1287c2bcWinson */
92e6c9073d81822496c038e70361e25b3f1287c2bcWinsonclass EventHandlerMethod {
93e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private Method mMethod;
94e6c9073d81822496c038e70361e25b3f1287c2bcWinson    Class<? extends EventBus.Event> eventType;
95e6c9073d81822496c038e70361e25b3f1287c2bcWinson
96e6c9073d81822496c038e70361e25b3f1287c2bcWinson    EventHandlerMethod(Method method, Class<? extends EventBus.Event> eventType) {
97e6c9073d81822496c038e70361e25b3f1287c2bcWinson        mMethod = method;
98e6c9073d81822496c038e70361e25b3f1287c2bcWinson        mMethod.setAccessible(true);
99e6c9073d81822496c038e70361e25b3f1287c2bcWinson        this.eventType = eventType;
100e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
101e6c9073d81822496c038e70361e25b3f1287c2bcWinson
102e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void invoke(Object target, EventBus.Event event)
103e6c9073d81822496c038e70361e25b3f1287c2bcWinson            throws InvocationTargetException, IllegalAccessException {
104e6c9073d81822496c038e70361e25b3f1287c2bcWinson        mMethod.invoke(target, event);
105e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
106e6c9073d81822496c038e70361e25b3f1287c2bcWinson
107e6c9073d81822496c038e70361e25b3f1287c2bcWinson    @Override
108e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public String toString() {
109e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return mMethod.getName() + "(" + eventType.getSimpleName() + ")";
110e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
111e6c9073d81822496c038e70361e25b3f1287c2bcWinson}
112e6c9073d81822496c038e70361e25b3f1287c2bcWinson
113e6c9073d81822496c038e70361e25b3f1287c2bcWinson/**
114e6c9073d81822496c038e70361e25b3f1287c2bcWinson * A simple in-process event bus.  It is simple because we can make assumptions about the state of
115e6c9073d81822496c038e70361e25b3f1287c2bcWinson * SystemUI and Recent's lifecycle.
116e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
117e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <p>
118e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Currently, there is a single EventBus that handles {@link EventBus.Event}s for each subscriber
119e6c9073d81822496c038e70361e25b3f1287c2bcWinson * on the main application thread.  Publishers can send() events to synchronously call subscribers
120e6c9073d81822496c038e70361e25b3f1287c2bcWinson * of that event, or post() events to be processed in the next run of the {@link Looper}.  In
121e6c9073d81822496c038e70361e25b3f1287c2bcWinson * addition, the EventBus supports sending and handling {@link EventBus.InterprocessEvent}s
122e6c9073d81822496c038e70361e25b3f1287c2bcWinson * (within the same package) implemented using standard {@link BroadcastReceiver} mechanism.
123e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Interprocess events must be posted using postInterprocess() to ensure that it is dispatched
124e6c9073d81822496c038e70361e25b3f1287c2bcWinson * correctly across processes.
125e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
126e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <p>
127e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Subscribers must be registered with a particular EventBus before they will receive events, and
128e6c9073d81822496c038e70361e25b3f1287c2bcWinson * handler methods must match a specific signature.
129e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
130e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <p>
131e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Event method signature:<ul>
132e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must be public final
133e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must return void
134e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must be called "onBusEvent"
135e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must take one parameter, of class type deriving from {@link EventBus.Event}
136e6c9073d81822496c038e70361e25b3f1287c2bcWinson * </ul>
137e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
138e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <p>
139e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Interprocess-Event method signature:<ul>
140e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must be public final
141e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must return void
142e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must be called "onInterprocessBusEvent"
143e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Methods must take one parameter, of class type deriving from {@link EventBus.InterprocessEvent}
144e6c9073d81822496c038e70361e25b3f1287c2bcWinson * </ul>
145e6c9073d81822496c038e70361e25b3f1287c2bcWinson * </p>
146e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
147e6c9073d81822496c038e70361e25b3f1287c2bcWinson * </p>
148e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Each subscriber can be registered with a given priority (default 1), and events will be dispatch
149e6c9073d81822496c038e70361e25b3f1287c2bcWinson * in decreasing order of priority.  For subscribers with the same priority, events will be
150e6c9073d81822496c038e70361e25b3f1287c2bcWinson * dispatched by latest registration time to earliest.
151e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
152e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <p>
153e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Interprocess events must extend {@link EventBus.InterprocessEvent}, have a constructor which
154e6c9073d81822496c038e70361e25b3f1287c2bcWinson * takes a {@link Bundle} and implement toBundle().  This allows us to serialize events to be sent
155e6c9073d81822496c038e70361e25b3f1287c2bcWinson * across processes.
156e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
157e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <p>
158e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Caveats:<ul>
159e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>The EventBus keeps a {@link WeakReference} to the publisher to prevent memory leaks, so
160e6c9073d81822496c038e70361e25b3f1287c2bcWinson * there must be another strong reference to the publisher for it to not get garbage-collected and
161e6c9073d81822496c038e70361e25b3f1287c2bcWinson * continue receiving events.
162e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Because the event handlers are called back using reflection, the EventBus is not intended
163e6c9073d81822496c038e70361e25b3f1287c2bcWinson * for use in tight, performance criticial loops.  For most user input/system callback events, this
164e6c9073d81822496c038e70361e25b3f1287c2bcWinson * is generally of low enough frequency to use the EventBus.
165e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Because the event handlers are called back using reflection, there will often be no
166e6c9073d81822496c038e70361e25b3f1287c2bcWinson * references to them from actual code.  The proguard configuration will be need to be updated to
167e6c9073d81822496c038e70361e25b3f1287c2bcWinson * keep these extra methods:
168e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
169e6c9073d81822496c038e70361e25b3f1287c2bcWinson * -keepclassmembers class ** {
170e6c9073d81822496c038e70361e25b3f1287c2bcWinson * public void onBusEvent(**);
171e6c9073d81822496c038e70361e25b3f1287c2bcWinson * public void onInterprocessBusEvent(**);
172e6c9073d81822496c038e70361e25b3f1287c2bcWinson * }
173e6c9073d81822496c038e70361e25b3f1287c2bcWinson * -keepclassmembers class ** extends **.EventBus$InterprocessEvent {
174e6c9073d81822496c038e70361e25b3f1287c2bcWinson * public <init>(android.os.Bundle);
175e6c9073d81822496c038e70361e25b3f1287c2bcWinson * }
176e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
177e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Subscriber registration can be expensive depending on the subscriber's {@link Class}.  This
178e6c9073d81822496c038e70361e25b3f1287c2bcWinson * is only done once per class type, but if possible, it is best to pre-register an instance of
179e6c9073d81822496c038e70361e25b3f1287c2bcWinson * that class beforehand or when idle.
180e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Each event should be sent once.  Events may hold internal information about the current
181e6c9073d81822496c038e70361e25b3f1287c2bcWinson * dispatch, or may be queued to be dispatched on another thread (if posted from a non-main thread),
182e6c9073d81822496c038e70361e25b3f1287c2bcWinson * so it may be unsafe to edit, change, or re-send the event again.
183e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>Events should follow a pattern of public-final POD (plain old data) objects, where they are
184e6c9073d81822496c038e70361e25b3f1287c2bcWinson * initialized by the constructor and read by each subscriber of that event.  Subscribers should
185e6c9073d81822496c038e70361e25b3f1287c2bcWinson * never alter events as they are processed, and this enforces that pattern.
186e6c9073d81822496c038e70361e25b3f1287c2bcWinson * </ul>
187e6c9073d81822496c038e70361e25b3f1287c2bcWinson *
188e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <p>
189e6c9073d81822496c038e70361e25b3f1287c2bcWinson * Future optimizations:
190e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>throw exception/log when a subscriber loses the reference
191e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>trace cost per registration & invocation
192e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>trace cross-process invocation
193e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>register(subscriber, Class&lt;?&gt;...) -- pass in exact class types you want registered
194e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>setSubscriberEventHandlerPriority(subscriber, Class<Event>, priority)
195e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>allow subscribers to implement interface, ie. EventBus.Subscriber, which lets then test a
196e6c9073d81822496c038e70361e25b3f1287c2bcWinson * message before invocation (ie. check if task id == this task id)
197e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>add postOnce() which automatically debounces
198e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>add postDelayed() which delays / postDelayedOnce() which delays and bounces
199e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>consolidate register() and registerInterprocess()
200e6c9073d81822496c038e70361e25b3f1287c2bcWinson * <li>sendForResult&lt;ReturnType&gt;(Event) to send and get a result, but who will send the
201e6c9073d81822496c038e70361e25b3f1287c2bcWinson * result?
202e6c9073d81822496c038e70361e25b3f1287c2bcWinson * </p>
203e6c9073d81822496c038e70361e25b3f1287c2bcWinson */
204e6c9073d81822496c038e70361e25b3f1287c2bcWinsonpublic class EventBus extends BroadcastReceiver {
205e6c9073d81822496c038e70361e25b3f1287c2bcWinson
2060d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson    private static final String TAG = "EventBus";
2070d14d4da91c3d8b1221269712d5abf43a7cf9f31Winson    private static final boolean DEBUG_TRACE_ALL = false;
208e6c9073d81822496c038e70361e25b3f1287c2bcWinson
209e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
210e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * An event super class that allows us to track internal event state across subscriber
211e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * invocations.
212e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *
213e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Events should not be edited by subscribers.
214e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
215e7f138c7f0a190c86cec10fb32fa106aacae4093Winson    public static class Event implements Cloneable {
216e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Indicates that this event's dispatch should be traced and logged to logcat
217e6c9073d81822496c038e70361e25b3f1287c2bcWinson        boolean trace;
218e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Indicates that this event must be posted on the EventBus's looper thread before invocation
219e6c9073d81822496c038e70361e25b3f1287c2bcWinson        boolean requiresPost;
220e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Not currently exposed, allows a subscriber to cancel further dispatch of this event
221e6c9073d81822496c038e70361e25b3f1287c2bcWinson        boolean cancelled;
222e6c9073d81822496c038e70361e25b3f1287c2bcWinson
223e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Only accessible from derived events
224e6c9073d81822496c038e70361e25b3f1287c2bcWinson        protected Event() {}
225e7f138c7f0a190c86cec10fb32fa106aacae4093Winson
226aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        /**
227aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         * Called by the EventBus prior to dispatching this event to any subscriber of this event.
228aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         */
229aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        void onPreDispatch() {
230aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            // Do nothing
231aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
232aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
233aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        /**
234aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         * Called by the EventBus after dispatching this event to every subscriber of this event.
235aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         */
236aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        void onPostDispatch() {
237aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            // Do nothing
238aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
239aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
240e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        @Override
241e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        protected Object clone() throws CloneNotSupportedException {
242e7f138c7f0a190c86cec10fb32fa106aacae4093Winson            Event evt = (Event) super.clone();
243e7f138c7f0a190c86cec10fb32fa106aacae4093Winson            // When cloning an event, reset the cancelled-dispatch state
244e7f138c7f0a190c86cec10fb32fa106aacae4093Winson            evt.cancelled = false;
245e7f138c7f0a190c86cec10fb32fa106aacae4093Winson            return evt;
246e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        }
247e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
248e6c9073d81822496c038e70361e25b3f1287c2bcWinson
249e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
250aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung     * An event that represents an animated state change, which allows subscribers to coordinate
251aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung     * callbacks which happen after the animation has taken place.
252aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung     *
253aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung     * Internally, it is guaranteed that increment() and decrement() will be called before and the
254aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung     * after the event is dispatched.
255aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung     */
256aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung    public static class AnimatedEvent extends Event {
257aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
258aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        private final ReferenceCountedTrigger mTrigger = new ReferenceCountedTrigger();
259aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
260aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        // Only accessible from derived events
261aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        protected AnimatedEvent() {}
262aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
263aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        /**
264aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         * Returns the reference counted trigger that coordinates the animations for this event.
265aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         */
266aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        public ReferenceCountedTrigger getAnimationTrigger() {
267aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            return mTrigger;
268aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
269aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
270aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        /**
271aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         * Adds a callback that is guaranteed to be called after the state has changed regardless of
272aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         * whether an actual animation took place.
273aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung         */
274aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        public void addPostAnimationCallback(Runnable r) {
275aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            mTrigger.addLastDecrementRunnable(r);
276aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
277aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
278aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        @Override
279aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        void onPreDispatch() {
280aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            mTrigger.increment();
281aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
282aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
283aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        @Override
284aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        void onPostDispatch() {
285aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            mTrigger.decrement();
286aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
287aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
288aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        @Override
289aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        protected Object clone() throws CloneNotSupportedException {
290aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            throw new CloneNotSupportedException();
291aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
292aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung    }
293aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
294aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung    /**
2955500390a006f2bbea565068234774a36cea076c0Winson     * An event that can be reusable, only used for situations where we want to reduce memory
2965500390a006f2bbea565068234774a36cea076c0Winson     * allocations when events are sent frequently (ie. on scroll).
2975500390a006f2bbea565068234774a36cea076c0Winson     */
2985500390a006f2bbea565068234774a36cea076c0Winson    public static class ReusableEvent extends Event {
2995500390a006f2bbea565068234774a36cea076c0Winson
3005500390a006f2bbea565068234774a36cea076c0Winson        private int mDispatchCount;
3015500390a006f2bbea565068234774a36cea076c0Winson
3025500390a006f2bbea565068234774a36cea076c0Winson        protected ReusableEvent() {}
3035500390a006f2bbea565068234774a36cea076c0Winson
3045500390a006f2bbea565068234774a36cea076c0Winson        @Override
3055500390a006f2bbea565068234774a36cea076c0Winson        void onPostDispatch() {
3065500390a006f2bbea565068234774a36cea076c0Winson            super.onPostDispatch();
3075500390a006f2bbea565068234774a36cea076c0Winson            mDispatchCount++;
3085500390a006f2bbea565068234774a36cea076c0Winson        }
3095500390a006f2bbea565068234774a36cea076c0Winson
3105500390a006f2bbea565068234774a36cea076c0Winson        @Override
3115500390a006f2bbea565068234774a36cea076c0Winson        protected Object clone() throws CloneNotSupportedException {
3125500390a006f2bbea565068234774a36cea076c0Winson            throw new CloneNotSupportedException();
3135500390a006f2bbea565068234774a36cea076c0Winson        }
3145500390a006f2bbea565068234774a36cea076c0Winson    }
3155500390a006f2bbea565068234774a36cea076c0Winson
3165500390a006f2bbea565068234774a36cea076c0Winson    /**
317e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * An inter-process event super class that allows us to track user state across subscriber
318e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * invocations.
319e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
320e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public static class InterprocessEvent extends Event {
321e6c9073d81822496c038e70361e25b3f1287c2bcWinson        private static final String EXTRA_USER = "_user";
322e6c9073d81822496c038e70361e25b3f1287c2bcWinson
323e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // The user which this event originated from
324e6c9073d81822496c038e70361e25b3f1287c2bcWinson        public final int user;
325e6c9073d81822496c038e70361e25b3f1287c2bcWinson
326e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Only accessible from derived events
327e6c9073d81822496c038e70361e25b3f1287c2bcWinson        protected InterprocessEvent(int user) {
328e6c9073d81822496c038e70361e25b3f1287c2bcWinson            this.user = user;
329e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
330e6c9073d81822496c038e70361e25b3f1287c2bcWinson
331e6c9073d81822496c038e70361e25b3f1287c2bcWinson        /**
332e6c9073d81822496c038e70361e25b3f1287c2bcWinson         * Called from the event bus
333e6c9073d81822496c038e70361e25b3f1287c2bcWinson         */
334e6c9073d81822496c038e70361e25b3f1287c2bcWinson        protected InterprocessEvent(Bundle b) {
335e6c9073d81822496c038e70361e25b3f1287c2bcWinson            user = b.getInt(EXTRA_USER);
336e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
337e6c9073d81822496c038e70361e25b3f1287c2bcWinson
338e6c9073d81822496c038e70361e25b3f1287c2bcWinson        protected Bundle toBundle() {
339e6c9073d81822496c038e70361e25b3f1287c2bcWinson            Bundle b = new Bundle();
340e6c9073d81822496c038e70361e25b3f1287c2bcWinson            b.putInt(EXTRA_USER, user);
341e6c9073d81822496c038e70361e25b3f1287c2bcWinson            return b;
342e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
343e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
344e6c9073d81822496c038e70361e25b3f1287c2bcWinson
345e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
346e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Proguard must also know, and keep, all methods matching this signature.
347e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *
348e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * -keepclassmembers class ** {
349e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *     public void onBusEvent(**);
350e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *     public void onInterprocessBusEvent(**);
351e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * }
352e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
353e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static final String METHOD_PREFIX = "onBusEvent";
354e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static final String INTERPROCESS_METHOD_PREFIX = "onInterprocessBusEvent";
355e6c9073d81822496c038e70361e25b3f1287c2bcWinson
356e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // Ensures that interprocess events can only be sent from a process holding this permission. */
357e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
358e6c9073d81822496c038e70361e25b3f1287c2bcWinson
359e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // Used for passing event data across process boundaries
360e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static final String EXTRA_INTERPROCESS_EVENT_BUNDLE = "interprocess_event_bundle";
361e6c9073d81822496c038e70361e25b3f1287c2bcWinson
362e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // The default priority of all subscribers
363e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static final int DEFAULT_SUBSCRIBER_PRIORITY = 1;
364e6c9073d81822496c038e70361e25b3f1287c2bcWinson
365e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // Orders the handlers by priority and registration time
366e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static final Comparator<EventHandler> EVENT_HANDLER_COMPARATOR = new Comparator<EventHandler>() {
367e6c9073d81822496c038e70361e25b3f1287c2bcWinson        @Override
368e6c9073d81822496c038e70361e25b3f1287c2bcWinson        public int compare(EventHandler h1, EventHandler h2) {
369e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // Rank the handlers by priority descending, followed by registration time descending.
370e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // aka. the later registered
371e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (h1.priority != h2.priority) {
372e6c9073d81822496c038e70361e25b3f1287c2bcWinson                return h2.priority - h1.priority;
373e6c9073d81822496c038e70361e25b3f1287c2bcWinson            } else {
374e6c9073d81822496c038e70361e25b3f1287c2bcWinson                return Long.compare(h2.subscriber.registrationTime, h1.subscriber.registrationTime);
375e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
376e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
377e6c9073d81822496c038e70361e25b3f1287c2bcWinson    };
378e6c9073d81822496c038e70361e25b3f1287c2bcWinson
379e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // Used for initializing the default bus
380e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static final Object sLock = new Object();
3814509b940fb7b9e7b013ea1d0d64621a683f92f7bIan Rogers    private static volatile EventBus sDefaultBus;
382e6c9073d81822496c038e70361e25b3f1287c2bcWinson
383e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // The handler to post all events
384e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private Handler mHandler;
385e6c9073d81822496c038e70361e25b3f1287c2bcWinson
386e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // Keep track of whether we have registered a broadcast receiver already, so that we can
387e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // unregister ourselves before re-registering again with a new IntentFilter.
388e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private boolean mHasRegisteredReceiver;
389e6c9073d81822496c038e70361e25b3f1287c2bcWinson
390e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
391e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Map from event class -> event handler list.  Keeps track of the actual mapping from event
392e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * to subscriber method.
393e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
394e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private HashMap<Class<? extends Event>, ArrayList<EventHandler>> mEventTypeMap = new HashMap<>();
395e6c9073d81822496c038e70361e25b3f1287c2bcWinson
396e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
397e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Map from subscriber class -> event handler method lists.  Used to determine upon registration
398e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * of a new subscriber whether we need to read all the subscriber's methods again using
399e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * reflection or whether we can just add the subscriber to the event type map.
400e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
401e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private HashMap<Class<? extends Object>, ArrayList<EventHandlerMethod>> mSubscriberTypeMap = new HashMap<>();
402e6c9073d81822496c038e70361e25b3f1287c2bcWinson
403e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
404e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Map from interprocess event name -> interprocess event class.  Used for mapping the event
405e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * name after receiving the broadcast, to the event type.  After which a new instance is created
406e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * and posted in the local process.
407e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
408e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private HashMap<String, Class<? extends InterprocessEvent>> mInterprocessEventNameMap = new HashMap<>();
409e6c9073d81822496c038e70361e25b3f1287c2bcWinson
410e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
411e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Set of all currently registered subscribers
412e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
413e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private ArrayList<Subscriber> mSubscribers = new ArrayList<>();
414e6c9073d81822496c038e70361e25b3f1287c2bcWinson
415e6c9073d81822496c038e70361e25b3f1287c2bcWinson    // For tracing
416e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private int mCallCount;
417e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private long mCallDurationMicros;
418e6c9073d81822496c038e70361e25b3f1287c2bcWinson
419e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
420e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Private constructor to create an event bus for a given looper.
421e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
422e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private EventBus(Looper looper) {
423e6c9073d81822496c038e70361e25b3f1287c2bcWinson        mHandler = new Handler(looper);
424e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
425e6c9073d81822496c038e70361e25b3f1287c2bcWinson
426e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
427e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @return the default event bus for the application's main thread.
428e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
429e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public static EventBus getDefault() {
430e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (sDefaultBus == null)
431e6c9073d81822496c038e70361e25b3f1287c2bcWinson        synchronized (sLock) {
432e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (sDefaultBus == null) {
433e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (DEBUG_TRACE_ALL) {
434e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    logWithPid("New EventBus");
435e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
436e6c9073d81822496c038e70361e25b3f1287c2bcWinson                sDefaultBus = new EventBus(Looper.getMainLooper());
437e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
438e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
439e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return sDefaultBus;
440e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
441e6c9073d81822496c038e70361e25b3f1287c2bcWinson
442e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
443e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Registers a subscriber to receive events with the default priority.
444e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *
445e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @param subscriber the subscriber to handle events.  If this is the first instance of the
446e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   subscriber's class type that has been registered, the class's methods will
447e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   be scanned for appropriate event handler methods.
448e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
449e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void register(Object subscriber) {
450e6c9073d81822496c038e70361e25b3f1287c2bcWinson        registerSubscriber(subscriber, DEFAULT_SUBSCRIBER_PRIORITY, null);
451e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
452e6c9073d81822496c038e70361e25b3f1287c2bcWinson
453e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
454e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Registers a subscriber to receive events with the given priority.
455e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *
456e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @param subscriber the subscriber to handle events.  If this is the first instance of the
457e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   subscriber's class type that has been registered, the class's methods will
458e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   be scanned for appropriate event handler methods.
459e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @param priority the priority that this subscriber will receive events relative to other
460e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                 subscribers
461e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
462e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void register(Object subscriber, int priority) {
463e6c9073d81822496c038e70361e25b3f1287c2bcWinson        registerSubscriber(subscriber, priority, null);
464e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
465e6c9073d81822496c038e70361e25b3f1287c2bcWinson
466e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
467e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Explicitly registers a subscriber to receive interprocess events with the default priority.
468e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *
469e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @param subscriber the subscriber to handle events.  If this is the first instance of the
470e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   subscriber's class type that has been registered, the class's methods will
471e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   be scanned for appropriate event handler methods.
472e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
473e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void registerInterprocessAsCurrentUser(Context context, Object subscriber) {
474e6c9073d81822496c038e70361e25b3f1287c2bcWinson        registerInterprocessAsCurrentUser(context, subscriber, DEFAULT_SUBSCRIBER_PRIORITY);
475e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
476e6c9073d81822496c038e70361e25b3f1287c2bcWinson
477e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
478e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Registers a subscriber to receive interprocess events with the given priority.
479e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *
480e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @param subscriber the subscriber to handle events.  If this is the first instance of the
481e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   subscriber's class type that has been registered, the class's methods will
482e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                   be scanned for appropriate event handler methods.
483e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @param priority the priority that this subscriber will receive events relative to other
484e6c9073d81822496c038e70361e25b3f1287c2bcWinson     *                 subscribers
485e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
486e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void registerInterprocessAsCurrentUser(Context context, Object subscriber, int priority) {
487e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
488e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("registerInterprocessAsCurrentUser(" + subscriber.getClass().getSimpleName() + ")");
489e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
490e6c9073d81822496c038e70361e25b3f1287c2bcWinson
491e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Register the subscriber normally, and update the broadcast receiver filter if this is
492e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // a new subscriber type with interprocess events
493e6c9073d81822496c038e70361e25b3f1287c2bcWinson        MutableBoolean hasInterprocessEventsChanged = new MutableBoolean(false);
494e6c9073d81822496c038e70361e25b3f1287c2bcWinson        registerSubscriber(subscriber, priority, hasInterprocessEventsChanged);
495e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
496e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("hasInterprocessEventsChanged: " + hasInterprocessEventsChanged.value);
497e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
498e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (hasInterprocessEventsChanged.value) {
499e6c9073d81822496c038e70361e25b3f1287c2bcWinson            registerReceiverForInterprocessEvents(context);
500e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
501e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
502e6c9073d81822496c038e70361e25b3f1287c2bcWinson
503e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
504e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Remove all EventHandlers pointing to the specified subscriber.  This does not remove the
505e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * mapping of subscriber type to event handler method, in case new instances of this subscriber
506e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * are registered.
507e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
508e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void unregister(Object subscriber) {
509e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
510e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("unregister()");
511e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
512e6c9073d81822496c038e70361e25b3f1287c2bcWinson
513e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Fail immediately if we are being called from the non-main thread
514e6c9073d81822496c038e70361e25b3f1287c2bcWinson        long callingThreadId = Thread.currentThread().getId();
515e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (callingThreadId != mHandler.getLooper().getThread().getId()) {
516e6c9073d81822496c038e70361e25b3f1287c2bcWinson            throw new RuntimeException("Can not unregister() a subscriber from a non-main thread.");
517e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
518e6c9073d81822496c038e70361e25b3f1287c2bcWinson
519e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Return early if this is not a registered subscriber
520e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (!findRegisteredSubscriber(subscriber, true /* removeFoundSubscriber */)) {
521e6c9073d81822496c038e70361e25b3f1287c2bcWinson            return;
522e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
523e6c9073d81822496c038e70361e25b3f1287c2bcWinson
524e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Class<?> subscriberType = subscriber.getClass();
525e6c9073d81822496c038e70361e25b3f1287c2bcWinson        ArrayList<EventHandlerMethod> subscriberMethods = mSubscriberTypeMap.get(subscriberType);
526e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (subscriberMethods != null) {
527e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // For each of the event handlers the subscriber handles, remove all references of that
528e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // handler
529e6c9073d81822496c038e70361e25b3f1287c2bcWinson            for (EventHandlerMethod method : subscriberMethods) {
530e6c9073d81822496c038e70361e25b3f1287c2bcWinson                ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(method.eventType);
531e6c9073d81822496c038e70361e25b3f1287c2bcWinson                for (int i = eventHandlers.size() - 1; i >= 0; i--) {
532e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    if (eventHandlers.get(i).subscriber.getReference() == subscriber) {
533e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        eventHandlers.remove(i);
534e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    }
535e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
536e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
537e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
538e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
539e6c9073d81822496c038e70361e25b3f1287c2bcWinson
540e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
541e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Explicit unregistration for interprocess event subscribers.  This actually behaves exactly
542e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * the same as unregister() since we also do not want to stop listening for specific
543e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * inter-process messages in case new instances of that subscriber is registered.
544e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
545e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void unregisterInterprocess(Context context, Object subscriber) {
546e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
547e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("unregisterInterprocess()");
548e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
549e6c9073d81822496c038e70361e25b3f1287c2bcWinson        unregister(subscriber);
550e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
551e6c9073d81822496c038e70361e25b3f1287c2bcWinson
552e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
553e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Sends an event to the subscribers of the given event type immediately.  This can only be
554e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * called from the same thread as the EventBus's looper thread (for the default EventBus, this
555e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * is the main application thread).
556e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
557e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void send(Event event) {
558e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Fail immediately if we are being called from the non-main thread
559e6c9073d81822496c038e70361e25b3f1287c2bcWinson        long callingThreadId = Thread.currentThread().getId();
560e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (callingThreadId != mHandler.getLooper().getThread().getId()) {
561e6c9073d81822496c038e70361e25b3f1287c2bcWinson            throw new RuntimeException("Can not send() a message from a non-main thread.");
562e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
563e6c9073d81822496c038e70361e25b3f1287c2bcWinson
564e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
565e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("send(" + event.getClass().getSimpleName() + ")");
566e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
567e6c9073d81822496c038e70361e25b3f1287c2bcWinson
568e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Reset the event's cancelled state
569e6c9073d81822496c038e70361e25b3f1287c2bcWinson        event.requiresPost = false;
570e6c9073d81822496c038e70361e25b3f1287c2bcWinson        event.cancelled = false;
571e6c9073d81822496c038e70361e25b3f1287c2bcWinson        queueEvent(event);
572e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
573e6c9073d81822496c038e70361e25b3f1287c2bcWinson
574e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
575e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Post a message to the subscribers of the given event type.  The messages will be posted on
576e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * the EventBus's looper thread (for the default EventBus, this is the main application thread).
577e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
578e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void post(Event event) {
579e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
580e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("post(" + event.getClass().getSimpleName() + ")");
581e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
582e6c9073d81822496c038e70361e25b3f1287c2bcWinson
583e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Reset the event's cancelled state
584e6c9073d81822496c038e70361e25b3f1287c2bcWinson        event.requiresPost = true;
585e6c9073d81822496c038e70361e25b3f1287c2bcWinson        event.cancelled = false;
586e6c9073d81822496c038e70361e25b3f1287c2bcWinson        queueEvent(event);
587e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
588e6c9073d81822496c038e70361e25b3f1287c2bcWinson
589dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    /**
590dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi     * If this method is called from the main thread, it will be handled directly. If this method
591dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi     * is not called from the main thread, it will be posted onto the main thread.
592dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi     */
593dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    public void sendOntoMainThread(Event event) {
594dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        long callingThreadId = Thread.currentThread().getId();
595dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        if (callingThreadId != mHandler.getLooper().getThread().getId()) {
596dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi            post(event);
597dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        } else {
598dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi            send(event);
599dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        }
600dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    }
601dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi
602e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /** Prevent post()ing an InterprocessEvent */
603e6c9073d81822496c038e70361e25b3f1287c2bcWinson    @Deprecated
604e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void post(InterprocessEvent event) {
605e6c9073d81822496c038e70361e25b3f1287c2bcWinson        throw new RuntimeException("Not supported, use postInterprocess");
606e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
607e6c9073d81822496c038e70361e25b3f1287c2bcWinson
608e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /** Prevent send()ing an InterprocessEvent */
609e6c9073d81822496c038e70361e25b3f1287c2bcWinson    @Deprecated
610e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void send(InterprocessEvent event) {
611e6c9073d81822496c038e70361e25b3f1287c2bcWinson        throw new RuntimeException("Not supported, use postInterprocess");
612e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
613e6c9073d81822496c038e70361e25b3f1287c2bcWinson
614e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
615e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Posts an interprocess event.
616e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
617e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void postInterprocess(Context context, final InterprocessEvent event) {
618e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
619e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("postInterprocess(" + event.getClass().getSimpleName() + ")");
620e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
621e6c9073d81822496c038e70361e25b3f1287c2bcWinson        String eventType = event.getClass().getName();
622e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Bundle eventBundle = event.toBundle();
623e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Intent intent = new Intent(eventType);
624e6c9073d81822496c038e70361e25b3f1287c2bcWinson        intent.setPackage(context.getPackageName());
625e6c9073d81822496c038e70361e25b3f1287c2bcWinson        intent.putExtra(EXTRA_INTERPROCESS_EVENT_BUNDLE, eventBundle);
626e6c9073d81822496c038e70361e25b3f1287c2bcWinson        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
627e6c9073d81822496c038e70361e25b3f1287c2bcWinson                Intent.FLAG_RECEIVER_FOREGROUND);
628e6c9073d81822496c038e70361e25b3f1287c2bcWinson        context.sendBroadcastAsUser(intent, UserHandle.ALL);
629e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
630e6c9073d81822496c038e70361e25b3f1287c2bcWinson
631e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
632e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Receiver for interprocess events.
633e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
634e6c9073d81822496c038e70361e25b3f1287c2bcWinson    @Override
635e6c9073d81822496c038e70361e25b3f1287c2bcWinson    public void onReceive(Context context, Intent intent) {
636e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
637e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("onReceive(" + intent.getAction() + ", user " + UserHandle.myUserId() + ")");
638e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
639e6c9073d81822496c038e70361e25b3f1287c2bcWinson
640e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Bundle eventBundle = intent.getBundleExtra(EXTRA_INTERPROCESS_EVENT_BUNDLE);
641e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Class<? extends InterprocessEvent> eventType = mInterprocessEventNameMap.get(intent.getAction());
642e6c9073d81822496c038e70361e25b3f1287c2bcWinson        try {
643e6c9073d81822496c038e70361e25b3f1287c2bcWinson            Constructor<? extends InterprocessEvent> ctor = eventType.getConstructor(Bundle.class);
644e6c9073d81822496c038e70361e25b3f1287c2bcWinson            send((Event) ctor.newInstance(eventBundle));
645e6c9073d81822496c038e70361e25b3f1287c2bcWinson        } catch (NoSuchMethodException|
646e6c9073d81822496c038e70361e25b3f1287c2bcWinson                InvocationTargetException|
647e6c9073d81822496c038e70361e25b3f1287c2bcWinson                InstantiationException|
648e6c9073d81822496c038e70361e25b3f1287c2bcWinson                IllegalAccessException e) {
649eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson            Log.e(TAG, "Failed to create InterprocessEvent", e.getCause());
650e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
651e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
652e6c9073d81822496c038e70361e25b3f1287c2bcWinson
653e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
654e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @return a dump of the current state of the EventBus
655e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
656d72c315d5eed3a684eee303364b97129cb821689Winson    public void dump(String prefix, PrintWriter writer) {
657d72c315d5eed3a684eee303364b97129cb821689Winson        writer.println(dumpInternal(prefix));
658d72c315d5eed3a684eee303364b97129cb821689Winson    }
659d72c315d5eed3a684eee303364b97129cb821689Winson
660d72c315d5eed3a684eee303364b97129cb821689Winson    public String dumpInternal(String prefix) {
661d72c315d5eed3a684eee303364b97129cb821689Winson        String innerPrefix = prefix + "  ";
662d72c315d5eed3a684eee303364b97129cb821689Winson        String innerInnerPrefix = innerPrefix + "  ";
663e6c9073d81822496c038e70361e25b3f1287c2bcWinson        StringBuilder output = new StringBuilder();
664d72c315d5eed3a684eee303364b97129cb821689Winson        output.append(prefix);
665e6c9073d81822496c038e70361e25b3f1287c2bcWinson        output.append("Registered class types:");
666e6c9073d81822496c038e70361e25b3f1287c2bcWinson        output.append("\n");
667d72c315d5eed3a684eee303364b97129cb821689Winson        ArrayList<Class<?>> subsciberTypes = new ArrayList<>(mSubscriberTypeMap.keySet());
668d72c315d5eed3a684eee303364b97129cb821689Winson        Collections.sort(subsciberTypes, new Comparator<Class<?>>() {
669d72c315d5eed3a684eee303364b97129cb821689Winson            @Override
670d72c315d5eed3a684eee303364b97129cb821689Winson            public int compare(Class<?> o1, Class<?> o2) {
671d72c315d5eed3a684eee303364b97129cb821689Winson                return o1.getSimpleName().compareTo(o2.getSimpleName());
672d72c315d5eed3a684eee303364b97129cb821689Winson            }
673d72c315d5eed3a684eee303364b97129cb821689Winson        });
674d72c315d5eed3a684eee303364b97129cb821689Winson        for (int i = 0; i < subsciberTypes.size(); i++) {
675d72c315d5eed3a684eee303364b97129cb821689Winson            Class<?> clz = subsciberTypes.get(i);
676d72c315d5eed3a684eee303364b97129cb821689Winson            output.append(innerPrefix);
677e6c9073d81822496c038e70361e25b3f1287c2bcWinson            output.append(clz.getSimpleName());
678e6c9073d81822496c038e70361e25b3f1287c2bcWinson            output.append("\n");
679e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
680d72c315d5eed3a684eee303364b97129cb821689Winson        output.append(prefix);
681e6c9073d81822496c038e70361e25b3f1287c2bcWinson        output.append("Event map:");
682e6c9073d81822496c038e70361e25b3f1287c2bcWinson        output.append("\n");
683d72c315d5eed3a684eee303364b97129cb821689Winson        ArrayList<Class<?>> classes = new ArrayList<>(mEventTypeMap.keySet());
684d72c315d5eed3a684eee303364b97129cb821689Winson        Collections.sort(classes, new Comparator<Class<?>>() {
685d72c315d5eed3a684eee303364b97129cb821689Winson            @Override
686d72c315d5eed3a684eee303364b97129cb821689Winson            public int compare(Class<?> o1, Class<?> o2) {
687d72c315d5eed3a684eee303364b97129cb821689Winson                return o1.getSimpleName().compareTo(o2.getSimpleName());
688d72c315d5eed3a684eee303364b97129cb821689Winson            }
689d72c315d5eed3a684eee303364b97129cb821689Winson        });
690d72c315d5eed3a684eee303364b97129cb821689Winson        for (int i = 0; i < classes.size(); i++) {
691d72c315d5eed3a684eee303364b97129cb821689Winson            Class<?> clz = classes.get(i);
692d72c315d5eed3a684eee303364b97129cb821689Winson            output.append(innerPrefix);
693e6c9073d81822496c038e70361e25b3f1287c2bcWinson            output.append(clz.getSimpleName());
694e6c9073d81822496c038e70361e25b3f1287c2bcWinson            output.append(" -> ");
695e6c9073d81822496c038e70361e25b3f1287c2bcWinson            output.append("\n");
696e6c9073d81822496c038e70361e25b3f1287c2bcWinson            ArrayList<EventHandler> handlers = mEventTypeMap.get(clz);
697e6c9073d81822496c038e70361e25b3f1287c2bcWinson            for (EventHandler handler : handlers) {
698e6c9073d81822496c038e70361e25b3f1287c2bcWinson                Object subscriber = handler.subscriber.getReference();
699e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (subscriber != null) {
700e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    String id = Integer.toHexString(System.identityHashCode(subscriber));
701d72c315d5eed3a684eee303364b97129cb821689Winson                    output.append(innerInnerPrefix);
702e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    output.append(subscriber.getClass().getSimpleName());
703e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    output.append(" [0x" + id + ", #" + handler.priority + "]");
704e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    output.append("\n");
705e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
706e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
707e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
708e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return output.toString();
709e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
710e6c9073d81822496c038e70361e25b3f1287c2bcWinson
711e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
712e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Registers a new subscriber.
713e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
714e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private void registerSubscriber(Object subscriber, int priority,
715e6c9073d81822496c038e70361e25b3f1287c2bcWinson            MutableBoolean hasInterprocessEventsChangedOut) {
716e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Fail immediately if we are being called from the non-main thread
717e6c9073d81822496c038e70361e25b3f1287c2bcWinson        long callingThreadId = Thread.currentThread().getId();
718e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (callingThreadId != mHandler.getLooper().getThread().getId()) {
719e6c9073d81822496c038e70361e25b3f1287c2bcWinson            throw new RuntimeException("Can not register() a subscriber from a non-main thread.");
720e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
721e6c9073d81822496c038e70361e25b3f1287c2bcWinson
722e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Return immediately if this exact subscriber is already registered
723e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (findRegisteredSubscriber(subscriber, false /* removeFoundSubscriber */)) {
724e6c9073d81822496c038e70361e25b3f1287c2bcWinson            return;
725e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
726e6c9073d81822496c038e70361e25b3f1287c2bcWinson
727e6c9073d81822496c038e70361e25b3f1287c2bcWinson        long t1 = 0;
728e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
729e6c9073d81822496c038e70361e25b3f1287c2bcWinson            t1 = SystemClock.currentTimeMicro();
730e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("registerSubscriber(" + subscriber.getClass().getSimpleName() + ")");
731e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
732e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Subscriber sub = new Subscriber(subscriber, SystemClock.uptimeMillis());
733e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Class<?> subscriberType = subscriber.getClass();
734e6c9073d81822496c038e70361e25b3f1287c2bcWinson        ArrayList<EventHandlerMethod> subscriberMethods = mSubscriberTypeMap.get(subscriberType);
735e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (subscriberMethods != null) {
736e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (DEBUG_TRACE_ALL) {
737e6c9073d81822496c038e70361e25b3f1287c2bcWinson                logWithPid("Subscriber class type already registered");
738e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
739e6c9073d81822496c038e70361e25b3f1287c2bcWinson
740e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // If we've parsed this subscriber type before, just add to the set for all the known
741e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // events
742e6c9073d81822496c038e70361e25b3f1287c2bcWinson            for (EventHandlerMethod method : subscriberMethods) {
743e6c9073d81822496c038e70361e25b3f1287c2bcWinson                ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(method.eventType);
744e6c9073d81822496c038e70361e25b3f1287c2bcWinson                eventTypeHandlers.add(new EventHandler(sub, method, priority));
745e6c9073d81822496c038e70361e25b3f1287c2bcWinson                sortEventHandlersByPriority(eventTypeHandlers);
746e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
747e6c9073d81822496c038e70361e25b3f1287c2bcWinson            mSubscribers.add(sub);
748e6c9073d81822496c038e70361e25b3f1287c2bcWinson            return;
749e6c9073d81822496c038e70361e25b3f1287c2bcWinson        } else {
750e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (DEBUG_TRACE_ALL) {
751e6c9073d81822496c038e70361e25b3f1287c2bcWinson                logWithPid("Subscriber class type requires registration");
752e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
753e6c9073d81822496c038e70361e25b3f1287c2bcWinson
754e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // If we are parsing this type from scratch, ensure we add it to the subscriber type
755e6c9073d81822496c038e70361e25b3f1287c2bcWinson            // map, and pull out he handler methods below
756e6c9073d81822496c038e70361e25b3f1287c2bcWinson            subscriberMethods = new ArrayList<>();
757e6c9073d81822496c038e70361e25b3f1287c2bcWinson            mSubscriberTypeMap.put(subscriberType, subscriberMethods);
758e6c9073d81822496c038e70361e25b3f1287c2bcWinson            mSubscribers.add(sub);
759e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
760e6c9073d81822496c038e70361e25b3f1287c2bcWinson
761e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Find all the valid event bus handler methods of the subscriber
762e6c9073d81822496c038e70361e25b3f1287c2bcWinson        MutableBoolean isInterprocessEvent = new MutableBoolean(false);
7632536c7ed446203ea12b38cf05a88e603f8d1b768Winson        Method[] methods = subscriberType.getDeclaredMethods();
764e6c9073d81822496c038e70361e25b3f1287c2bcWinson        for (Method m : methods) {
765e6c9073d81822496c038e70361e25b3f1287c2bcWinson            Class<?>[] parameterTypes = m.getParameterTypes();
766e6c9073d81822496c038e70361e25b3f1287c2bcWinson            isInterprocessEvent.value = false;
767e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (isValidEventBusHandlerMethod(m, parameterTypes, isInterprocessEvent)) {
768e6c9073d81822496c038e70361e25b3f1287c2bcWinson                Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];
769e6c9073d81822496c038e70361e25b3f1287c2bcWinson                ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(eventType);
770e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (eventTypeHandlers == null) {
771e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    eventTypeHandlers = new ArrayList<>();
772e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    mEventTypeMap.put(eventType, eventTypeHandlers);
773e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
774e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (isInterprocessEvent.value) {
775e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    try {
776e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        // Enforce that the event must have a Bundle constructor
777e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        eventType.getConstructor(Bundle.class);
778e6c9073d81822496c038e70361e25b3f1287c2bcWinson
779e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        mInterprocessEventNameMap.put(eventType.getName(),
780e6c9073d81822496c038e70361e25b3f1287c2bcWinson                                (Class<? extends InterprocessEvent>) eventType);
781e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        if (hasInterprocessEventsChangedOut != null) {
782e6c9073d81822496c038e70361e25b3f1287c2bcWinson                            hasInterprocessEventsChangedOut.value = true;
783e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        }
784e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    } catch (NoSuchMethodException e) {
785e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        throw new RuntimeException("Expected InterprocessEvent to have a Bundle constructor");
786e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    }
787e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
788e6c9073d81822496c038e70361e25b3f1287c2bcWinson                EventHandlerMethod method = new EventHandlerMethod(m, eventType);
789e6c9073d81822496c038e70361e25b3f1287c2bcWinson                EventHandler handler = new EventHandler(sub, method, priority);
790e6c9073d81822496c038e70361e25b3f1287c2bcWinson                eventTypeHandlers.add(handler);
791e6c9073d81822496c038e70361e25b3f1287c2bcWinson                subscriberMethods.add(method);
792e6c9073d81822496c038e70361e25b3f1287c2bcWinson                sortEventHandlersByPriority(eventTypeHandlers);
793e6c9073d81822496c038e70361e25b3f1287c2bcWinson
794e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (DEBUG_TRACE_ALL) {
795e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    logWithPid("  * Method: " + m.getName() +
796e6c9073d81822496c038e70361e25b3f1287c2bcWinson                            " event: " + parameterTypes[0].getSimpleName() +
797e6c9073d81822496c038e70361e25b3f1287c2bcWinson                            " interprocess? " + isInterprocessEvent.value);
798e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
799e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
800e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
801e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
802e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("Registered " + subscriber.getClass().getSimpleName() + " in " +
803e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    (SystemClock.currentTimeMicro() - t1) + " microseconds");
804e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
805e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
806e6c9073d81822496c038e70361e25b3f1287c2bcWinson
807e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
808e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Adds a new message.
809e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
810e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private void queueEvent(final Event event) {
811e6c9073d81822496c038e70361e25b3f1287c2bcWinson        ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(event.getClass());
812e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (eventHandlers == null) {
813b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung            // This is just an optimization to return early if there are no handlers. However, we
814b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung            // should still ensure that we call pre/post dispatch callbacks so that AnimatedEvents
815b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung            // are still cleaned up correctly if a listener has not been registered to handle them
816b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung            event.onPreDispatch();
817b502690e2d0a120993279a6fe800ad07dccc8872Winson Chung            event.onPostDispatch();
818e6c9073d81822496c038e70361e25b3f1287c2bcWinson            return;
819e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
820aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
821aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        // Prepare this event
822aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        boolean hasPostedEvent = false;
823aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        event.onPreDispatch();
824aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
825e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // We need to clone the list in case a subscriber unregisters itself during traversal
8265500390a006f2bbea565068234774a36cea076c0Winson        // TODO: Investigate whether we can skip the object creation here
827e6c9073d81822496c038e70361e25b3f1287c2bcWinson        eventHandlers = (ArrayList<EventHandler>) eventHandlers.clone();
8285500390a006f2bbea565068234774a36cea076c0Winson        int eventHandlerCount = eventHandlers.size();
8295500390a006f2bbea565068234774a36cea076c0Winson        for (int i = 0; i < eventHandlerCount; i++) {
8305500390a006f2bbea565068234774a36cea076c0Winson            final EventHandler eventHandler = eventHandlers.get(i);
831e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (eventHandler.subscriber.getReference() != null) {
832e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (event.requiresPost) {
833e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    mHandler.post(new Runnable() {
834e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        @Override
835e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        public void run() {
836e6c9073d81822496c038e70361e25b3f1287c2bcWinson                            processEvent(eventHandler, event);
837e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        }
838e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    });
839aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung                    hasPostedEvent = true;
840e6c9073d81822496c038e70361e25b3f1287c2bcWinson                } else {
841e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    processEvent(eventHandler, event);
842e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
843e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
844e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
845aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung
846aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        // Clean up after this event, deferring until all subscribers have been called
847aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        if (hasPostedEvent) {
848aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            mHandler.post(new Runnable() {
849aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung                @Override
850aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung                public void run() {
851aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung                    event.onPostDispatch();
852aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung                }
853aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            });
854aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        } else {
855aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung            event.onPostDispatch();
856aaeaac17831090594e4927b1531c4658d239a3eaWinson Chung        }
857e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
858e6c9073d81822496c038e70361e25b3f1287c2bcWinson
859e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
860e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Processes and dispatches the given event to the given event handler, on the thread of whoever
861e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * calls this method.
862e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
863e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private void processEvent(final EventHandler eventHandler, final Event event) {
864e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Skip if the event was already cancelled
865e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (event.cancelled) {
866e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (event.trace || DEBUG_TRACE_ALL) {
867e6c9073d81822496c038e70361e25b3f1287c2bcWinson                logWithPid("Event dispatch cancelled");
868e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
869e6c9073d81822496c038e70361e25b3f1287c2bcWinson            return;
870e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
871e6c9073d81822496c038e70361e25b3f1287c2bcWinson
872e6c9073d81822496c038e70361e25b3f1287c2bcWinson        try {
873e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (event.trace || DEBUG_TRACE_ALL) {
874e6c9073d81822496c038e70361e25b3f1287c2bcWinson                logWithPid(" -> " + eventHandler.toString());
875e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
876e6c9073d81822496c038e70361e25b3f1287c2bcWinson            Object sub = eventHandler.subscriber.getReference();
877e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (sub != null) {
878e6c9073d81822496c038e70361e25b3f1287c2bcWinson                long t1 = 0;
879e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (DEBUG_TRACE_ALL) {
880e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    t1 = SystemClock.currentTimeMicro();
881e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
882e6c9073d81822496c038e70361e25b3f1287c2bcWinson                eventHandler.method.invoke(sub, event);
883e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (DEBUG_TRACE_ALL) {
884e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    long duration = (SystemClock.currentTimeMicro() - t1);
885e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    mCallDurationMicros += duration;
886e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    mCallCount++;
887e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    logWithPid(eventHandler.method.toString() + " duration: " + duration +
888e6c9073d81822496c038e70361e25b3f1287c2bcWinson                            " microseconds, avg: " + (mCallDurationMicros / mCallCount));
889e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
890e6c9073d81822496c038e70361e25b3f1287c2bcWinson            } else {
891e6c9073d81822496c038e70361e25b3f1287c2bcWinson                Log.e(TAG, "Failed to deliver event to null subscriber");
892e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
893e6c9073d81822496c038e70361e25b3f1287c2bcWinson        } catch (IllegalAccessException e) {
894eca4ab6e99bcb2a7b31b8b4b1c3b5474297b6b25Winson            Log.e(TAG, "Failed to invoke method", e.getCause());
895e6c9073d81822496c038e70361e25b3f1287c2bcWinson        } catch (InvocationTargetException e) {
8965b7dd536aa6cb8ce323b47cee109f879feb0d33aWinson            throw new RuntimeException(e.getCause());
897e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
898e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
899e6c9073d81822496c038e70361e25b3f1287c2bcWinson
900e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
901e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Re-registers the broadcast receiver for any new messages that we want to listen for.
902e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
903e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private void registerReceiverForInterprocessEvents(Context context) {
904e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (DEBUG_TRACE_ALL) {
905e6c9073d81822496c038e70361e25b3f1287c2bcWinson            logWithPid("registerReceiverForInterprocessEvents()");
906e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
907e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Rebuild the receiver filter with the new interprocess events
908e6c9073d81822496c038e70361e25b3f1287c2bcWinson        IntentFilter filter = new IntentFilter();
909e6c9073d81822496c038e70361e25b3f1287c2bcWinson        for (String eventName : mInterprocessEventNameMap.keySet()) {
910e6c9073d81822496c038e70361e25b3f1287c2bcWinson            filter.addAction(eventName);
911e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (DEBUG_TRACE_ALL) {
912e6c9073d81822496c038e70361e25b3f1287c2bcWinson                logWithPid("  filter: " + eventName);
913e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
914e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
915e6c9073d81822496c038e70361e25b3f1287c2bcWinson        // Re-register the receiver with the new filter
916e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (mHasRegisteredReceiver) {
917e6c9073d81822496c038e70361e25b3f1287c2bcWinson            context.unregisterReceiver(this);
918e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
919e6c9073d81822496c038e70361e25b3f1287c2bcWinson        context.registerReceiverAsUser(this, UserHandle.ALL, filter, PERMISSION_SELF, mHandler);
920e6c9073d81822496c038e70361e25b3f1287c2bcWinson        mHasRegisteredReceiver = true;
921e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
922e6c9073d81822496c038e70361e25b3f1287c2bcWinson
923e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
924e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Returns whether this subscriber is currently registered.  If {@param removeFoundSubscriber}
925e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * is true, then remove the subscriber before returning.
926e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
927e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private boolean findRegisteredSubscriber(Object subscriber, boolean removeFoundSubscriber) {
928e6c9073d81822496c038e70361e25b3f1287c2bcWinson        for (int i = mSubscribers.size() - 1; i >= 0; i--) {
929e6c9073d81822496c038e70361e25b3f1287c2bcWinson            Subscriber sub = mSubscribers.get(i);
930e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (sub.getReference() == subscriber) {
931e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (removeFoundSubscriber) {
932e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    mSubscribers.remove(i);
933e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
934e6c9073d81822496c038e70361e25b3f1287c2bcWinson                return true;
935e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
936e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
937e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return false;
938e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
939e6c9073d81822496c038e70361e25b3f1287c2bcWinson
940e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
941e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * @return whether {@param method} is a valid (normal or interprocess) event bus handler method
942e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
943e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private boolean isValidEventBusHandlerMethod(Method method, Class<?>[] parameterTypes,
944e6c9073d81822496c038e70361e25b3f1287c2bcWinson            MutableBoolean isInterprocessEventOut) {
945e6c9073d81822496c038e70361e25b3f1287c2bcWinson        int modifiers = method.getModifiers();
946e6c9073d81822496c038e70361e25b3f1287c2bcWinson        if (Modifier.isPublic(modifiers) &&
947e6c9073d81822496c038e70361e25b3f1287c2bcWinson                Modifier.isFinal(modifiers) &&
948e6c9073d81822496c038e70361e25b3f1287c2bcWinson                method.getReturnType().equals(Void.TYPE) &&
949e6c9073d81822496c038e70361e25b3f1287c2bcWinson                parameterTypes.length == 1) {
950e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (EventBus.InterprocessEvent.class.isAssignableFrom(parameterTypes[0]) &&
951e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    method.getName().startsWith(INTERPROCESS_METHOD_PREFIX)) {
952e6c9073d81822496c038e70361e25b3f1287c2bcWinson                isInterprocessEventOut.value = true;
953e6c9073d81822496c038e70361e25b3f1287c2bcWinson                return true;
954e6c9073d81822496c038e70361e25b3f1287c2bcWinson            } else if (EventBus.Event.class.isAssignableFrom(parameterTypes[0]) &&
955e6c9073d81822496c038e70361e25b3f1287c2bcWinson                            method.getName().startsWith(METHOD_PREFIX)) {
956e6c9073d81822496c038e70361e25b3f1287c2bcWinson                isInterprocessEventOut.value = false;
957e6c9073d81822496c038e70361e25b3f1287c2bcWinson                return true;
958e6c9073d81822496c038e70361e25b3f1287c2bcWinson            } else {
959e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (DEBUG_TRACE_ALL) {
960e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    if (!EventBus.Event.class.isAssignableFrom(parameterTypes[0])) {
961e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        logWithPid("  Expected method take an Event-based parameter: " + method.getName());
962e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    } else if (!method.getName().startsWith(INTERPROCESS_METHOD_PREFIX) &&
963e6c9073d81822496c038e70361e25b3f1287c2bcWinson                            !method.getName().startsWith(METHOD_PREFIX)) {
964e6c9073d81822496c038e70361e25b3f1287c2bcWinson                        logWithPid("  Expected method start with method prefix: " + method.getName());
965e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    }
966e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
967e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
968e6c9073d81822496c038e70361e25b3f1287c2bcWinson        } else {
969e6c9073d81822496c038e70361e25b3f1287c2bcWinson            if (DEBUG_TRACE_ALL) {
970e6c9073d81822496c038e70361e25b3f1287c2bcWinson                if (!Modifier.isPublic(modifiers)) {
971e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    logWithPid("  Expected method to be public: " + method.getName());
972e6c9073d81822496c038e70361e25b3f1287c2bcWinson                } else if (!Modifier.isFinal(modifiers)) {
973e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    logWithPid("  Expected method to be final: " + method.getName());
974e6c9073d81822496c038e70361e25b3f1287c2bcWinson                } else if (!method.getReturnType().equals(Void.TYPE)) {
975e6c9073d81822496c038e70361e25b3f1287c2bcWinson                    logWithPid("  Expected method to return null: " + method.getName());
976e6c9073d81822496c038e70361e25b3f1287c2bcWinson                }
977e6c9073d81822496c038e70361e25b3f1287c2bcWinson            }
978e6c9073d81822496c038e70361e25b3f1287c2bcWinson        }
979e6c9073d81822496c038e70361e25b3f1287c2bcWinson        return false;
980e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
981e6c9073d81822496c038e70361e25b3f1287c2bcWinson
982e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
983e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Sorts the event handlers by priority and registration time.
984e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
985e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private void sortEventHandlersByPriority(List<EventHandler> eventHandlers) {
986e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Collections.sort(eventHandlers, EVENT_HANDLER_COMPARATOR);
987e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
988e6c9073d81822496c038e70361e25b3f1287c2bcWinson
989e6c9073d81822496c038e70361e25b3f1287c2bcWinson    /**
990e6c9073d81822496c038e70361e25b3f1287c2bcWinson     * Helper method to log the given {@param text} with the current process and user id.
991e6c9073d81822496c038e70361e25b3f1287c2bcWinson     */
992e6c9073d81822496c038e70361e25b3f1287c2bcWinson    private static void logWithPid(String text) {
993e6c9073d81822496c038e70361e25b3f1287c2bcWinson        Log.d(TAG, "[" + android.os.Process.myPid() + ", u" + UserHandle.myUserId() + "] " + text);
994e6c9073d81822496c038e70361e25b3f1287c2bcWinson    }
995e6c9073d81822496c038e70361e25b3f1287c2bcWinson}
996