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<?>...) -- 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<ReturnType>(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