[
  {
    "path": ".github/workflows/gradle.yml",
    "content": "# This workflow will build a Java project with Gradle\n# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle\n\nname: Java CI with Gradle\n\non:\n  push:\n  pull_request:\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v3\n      - name: Set up JDK 11\n        uses: actions/setup-java@v3\n        with:\n          java-version: '11'\n          distribution: 'temurin'\n          cache: gradle\n      - name: Grant execute permission for gradlew\n        run: chmod +x gradlew\n      - name: Gradle Info\n        run: ./gradlew -version\n      - name: Build with Gradle\n        run: ./gradlew build\n"
  },
  {
    "path": ".gitignore",
    "content": "# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\nrelease/\n\n# Gradle files\n.gradle/\nbuild/\ngradle.properties\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# IntelliJ project files\n*.iml\n.idea/\n\n# Eclipse project files\n.settings/\n\n# Misc\n.DS_Store\n"
  },
  {
    "path": "COMPARISON.md",
    "content": "EventBus Comparison\n===================\n\nComparison with Square's Otto\n-----------------------------\nOtto is another event bus library for Android; actually it's a fork of Guava's EventBus. greenrobot's EventBus and Otto share some basic semantics (register, post, unregister, ...), but there are differences which the following table summarizes:\n<table>\n    <tr>\n        <th></th>\n        <th>EventBus</th>\n        <th>Otto</th>\n    </tr>\n    <tr>\n        <th>Declare event handling methods</th>\n        <td>Annotations (since 3.0, can be precompiled for best performance)</td>\n        <td>Annotations</td>\n    </tr>\n    <tr>\n        <th>Event inheritance</th>\n        <td>Yes</td>\n        <td>Yes</td>\n    </tr>\n    <tr>\n        <th>Subscriber inheritance</th>\n        <td>Yes</td>\n        <td>No</td>\n    </tr>\n    <tr>\n        <th>Cache most recent events</th>\n        <td>Yes, sticky events</td>\n        <td>No</td>\n    </tr>\n    <tr>\n        <th>Event producers (e.g. for coding cached events)</th>\n        <td>No</td>\n        <td>Yes</td>\n    </tr>\n    <tr>\n        <th>Event delivery in posting thread</th>\n        <td>Yes (Default)</td>\n        <td>Yes</td>\n    </tr>\n    <tr>\n        <th>Event delivery in main thread</th>\n        <td>Yes</td>\n        <td>No</td>\n    </tr>\n    <tr>\n        <th>Event delivery in background thread</th>\n        <td>Yes</td>\n        <td>No</td>\n    </tr>\n    <tr>\n        <th>Asynchronous event delivery</th>\n        <td>Yes</td>\n        <td>No</td>\n    </tr>\n</table>\n\n_**Note:** the following information is outdated, preprocessed annotations are much faster than EventBus 2.x, on which the following table is based._\n\nBesides features, performance is another differentiator. To compare performance, we created an Android application, which is also part of this repository (EventBusPerformance). You can also run the app on your phone to benchmark different scenarios.\n\nTODO: Update for EventBus 3 with and without index.\n\nBenchmark results indicate that EventBus is significantly faster in almost every scenario:\n<table>\n    <tr>\n        <th></th>\n        <th>EventBus</th>\n        <th>Otto</th>\n    </tr>\n    <tr>\n        <th>Posting 1000 events, Android 2.3 emulator</th>\n        <td>~70% faster</td>\n        <td></td>\n    </tr>\n\t<tr>\n        <th>Posting 1000 events, S3 Android 4.0</th>\n        <td>~110% faster</td>\n        <td></td>\n    </tr>\n    <tr>\n        <th>Register 1000 subscribers, Android 2.3 emulator</th>\n        <td>~10% faster</td>\n        <td></td>\n    </tr>\n    <tr>\n        <th>Register 1000 subscribers, S3 Android 4.0</th>\n        <td>~70% faster</td>\n        <td></td>\n    </tr>\n    <tr>\n        <th>Register subscribers cold start, Android 2.3 emulator</th>\n        <td>~350% faster</td>\n        <td></td>\n    </tr>\t\n    <tr>\n        <th>Register subscribers cold start, S3 Android 4.0</th>\n        <td colspan=\"2\">About the same</td>\n    </tr>\t\n</table>\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Before you create an Issue...\n=============================\n\nThere are better Places for Support\n-----------------------------------\nWe want your question to be answered, so it is important that you ask at the right place. Be aware that an issue tracker is not the best place to ask for support. An issue tracker is used to track issues (bugs or feature requests).\nInstead, please use [stackoverflow.com](https://stackoverflow.com/questions/tagged/greenrobot-eventbus?sort=frequent) and use the tag [greenrobot-eventbus](http://stackoverflow.com/tags/greenrobot-eventbus/info) for your question.\n\nIf you want professional support, check http://greenrobot.org/contact-support/.\n\nExamples for support questions that are more likely to be answered on StackOverflow:\n\n* Asking how something works\n* Asking how to use EventBus in a specific scenario\n* Your app crashes/misbehaves and you are not sure why\n\nThe perfect Issue Report\n------------------------\nA couple of simple steps can save time for everyone.\n\nCheck before reporting:\n\n* It's not a support inquiry\n* You have read the docs\n* You searched the web and stackoverflow\n* You searched existing issues to avoid duplicates\n\nReporting bugs:\n\n * Please investigate if is the bug is really caused by the library. Isolate the issue: what's the minimal code to reproduce the bug?\n * Bonus steps to gain extra karma points: once you isolated and identified the issue, you can prepare an push request. Submit an unit test causing the bug, and ideally a fix for the bug.\n\nRequesting features:\n\n * Ask yourself: is the feature useful for a majority users? One of our major goals is to keep the API simple and concise. We do not want to cover all possible use cases, but those that make 80% of users happy.\n\nA Note on Pull Requests\n=======================\nPull requests (and issues) may queue up up a bit. Usually, pull requests and issues are checked when new releases are planned.\n\nFor bigger pull requests, it's a good idea to check with the maintainer upfront about the idea and the implementation outline.\n\nThanks for reading!\n===================\nIt's your contributions and feedback that makes maintaining this library fun.\n"
  },
  {
    "path": "EventBus/build.gradle",
    "content": "apply plugin: 'java'\n\ngroup = rootProject.group\nversion = rootProject.version\n\njava.sourceCompatibility = JavaVersion.VERSION_1_8\njava.targetCompatibility = JavaVersion.VERSION_1_8\n\nsourceSets {\n    main {\n        java {\n            srcDir 'src'\n            // exclude 'de/greenrobot/event/util/**'\n        }\n    }\n}\n\njavadoc {\n    failOnError = false\n    title = \"EventBus ${version} API\"\n\toptions.bottom = 'Available under the Apache License, Version 2.0 - <i>Copyright &#169; 2012-2020 <a href=\"https://greenrobot.org\">greenrobot.org</a>. All Rights Reserved.</i>'\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    archiveClassifier.set(\"javadoc\")\n    from 'build/docs/javadoc'\n}\n\ntask sourcesJar(type: Jar) {\n    archiveClassifier.set(\"sources\")\n    from sourceSets.main.allSource\n}\n\napply from: rootProject.file(\"gradle/publish.gradle\")\n// Set project-specific properties\nafterEvaluate {\n    publishing.publications {\n        mavenJava(MavenPublication) {\n            artifactId = \"eventbus-java\"\n\n            from components.java\n            artifact javadocJar\n            artifact sourcesJar\n            pom {\n                name = \"EventBus\"\n                description = \"EventBus is a publish/subscribe event bus.\"\n                packaging = \"jar\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/AsyncPoster.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\n\n/**\n * Posts events in background.\n * \n * @author Markus\n */\nclass AsyncPoster implements Runnable, Poster {\n\n    private final PendingPostQueue queue;\n    private final EventBus eventBus;\n\n    AsyncPoster(EventBus eventBus) {\n        this.eventBus = eventBus;\n        queue = new PendingPostQueue();\n    }\n\n    public void enqueue(Subscription subscription, Object event) {\n        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);\n        queue.enqueue(pendingPost);\n        eventBus.getExecutorService().execute(this);\n    }\n\n    @Override\n    public void run() {\n        PendingPost pendingPost = queue.poll();\n        if(pendingPost == null) {\n            throw new IllegalStateException(\"No pending post available\");\n        }\n        eventBus.invokeSubscriber(pendingPost);\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport java.util.logging.Level;\n\n/**\n * Posts events in background.\n *\n * @author Markus\n */\nfinal class BackgroundPoster implements Runnable, Poster {\n\n    private final PendingPostQueue queue;\n    private final EventBus eventBus;\n\n    private volatile boolean executorRunning;\n\n    BackgroundPoster(EventBus eventBus) {\n        this.eventBus = eventBus;\n        queue = new PendingPostQueue();\n    }\n\n    public void enqueue(Subscription subscription, Object event) {\n        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);\n        synchronized (this) {\n            queue.enqueue(pendingPost);\n            if (!executorRunning) {\n                executorRunning = true;\n                eventBus.getExecutorService().execute(this);\n            }\n        }\n    }\n\n    @Override\n    public void run() {\n        try {\n            try {\n                while (true) {\n                    PendingPost pendingPost = queue.poll(1000);\n                    if (pendingPost == null) {\n                        synchronized (this) {\n                            // Check again, this time in synchronized\n                            pendingPost = queue.poll();\n                            if (pendingPost == null) {\n                                executorRunning = false;\n                                return;\n                            }\n                        }\n                    }\n                    eventBus.invokeSubscriber(pendingPost);\n                }\n            } catch (InterruptedException e) {\n                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + \" was interrupted\", e);\n            }\n        } finally {\n            executorRunning = false;\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/EventBus.java",
    "content": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.greenrobot.eventbus.android.AndroidDependenciesDetector;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.ExecutorService;\nimport java.util.logging.Level;\n\n/**\n * EventBus is a central publish/subscribe event system for Java and Android.\n * Events are posted ({@link #post(Object)}) to the bus, which delivers it to subscribers that have a matching handler\n * method for the event type.\n * To receive events, subscribers must register themselves to the bus using {@link #register(Object)}.\n * Once registered, subscribers receive events until {@link #unregister(Object)} is called.\n * Event handling methods must be annotated by {@link Subscribe}, must be public, return nothing (void),\n * and have exactly one parameter (the event).\n *\n * @author Markus Junginger, greenrobot\n */\npublic class EventBus {\n\n    /** Log tag, apps may override it. */\n    public static String TAG = \"EventBus\";\n\n    static volatile EventBus defaultInstance;\n\n    private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();\n    private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();\n\n    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;\n    private final Map<Object, List<Class<?>>> typesBySubscriber;\n    private final Map<Class<?>, Object> stickyEvents;\n\n    private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {\n        @Override\n        protected PostingThreadState initialValue() {\n            return new PostingThreadState();\n        }\n    };\n\n    // @Nullable\n    private final MainThreadSupport mainThreadSupport;\n    // @Nullable\n    private final Poster mainThreadPoster;\n    private final BackgroundPoster backgroundPoster;\n    private final AsyncPoster asyncPoster;\n    private final SubscriberMethodFinder subscriberMethodFinder;\n    private final ExecutorService executorService;\n\n    private final boolean throwSubscriberException;\n    private final boolean logSubscriberExceptions;\n    private final boolean logNoSubscriberMessages;\n    private final boolean sendSubscriberExceptionEvent;\n    private final boolean sendNoSubscriberEvent;\n    private final boolean eventInheritance;\n\n    private final int indexCount;\n    private final Logger logger;\n\n    /** Convenience singleton for apps using a process-wide EventBus instance. */\n    public static EventBus getDefault() {\n        EventBus instance = defaultInstance;\n        if (instance == null) {\n            synchronized (EventBus.class) {\n                instance = EventBus.defaultInstance;\n                if (instance == null) {\n                    instance = EventBus.defaultInstance = new EventBus();\n                }\n            }\n        }\n        return instance;\n    }\n\n    public static EventBusBuilder builder() {\n        return new EventBusBuilder();\n    }\n\n    /** For unit test primarily. */\n    public static void clearCaches() {\n        SubscriberMethodFinder.clearCaches();\n        eventTypesCache.clear();\n    }\n\n    /**\n     * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a\n     * central bus, consider {@link #getDefault()}.\n     */\n    public EventBus() {\n        this(DEFAULT_BUILDER);\n    }\n\n    EventBus(EventBusBuilder builder) {\n        logger = builder.getLogger();\n        subscriptionsByEventType = new HashMap<>();\n        typesBySubscriber = new HashMap<>();\n        stickyEvents = new ConcurrentHashMap<>();\n        mainThreadSupport = builder.getMainThreadSupport();\n        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;\n        backgroundPoster = new BackgroundPoster(this);\n        asyncPoster = new AsyncPoster(this);\n        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;\n        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,\n                builder.strictMethodVerification, builder.ignoreGeneratedIndex);\n        logSubscriberExceptions = builder.logSubscriberExceptions;\n        logNoSubscriberMessages = builder.logNoSubscriberMessages;\n        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;\n        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;\n        throwSubscriberException = builder.throwSubscriberException;\n        eventInheritance = builder.eventInheritance;\n        executorService = builder.executorService;\n    }\n\n    /**\n     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they\n     * are no longer interested in receiving events.\n     * <p/>\n     * Subscribers have event handling methods that must be annotated by {@link Subscribe}.\n     * The {@link Subscribe} annotation also allows configuration like {@link\n     * ThreadMode} and priority.\n     */\n    public void register(Object subscriber) {\n        if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) {\n            // Crash if the user (developer) has not imported the Android compatibility library.\n            throw new RuntimeException(\"It looks like you are using EventBus on Android, \" +\n                    \"make sure to add the \\\"eventbus\\\" Android library to your dependencies.\");\n        }\n\n        Class<?> subscriberClass = subscriber.getClass();\n        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);\n        synchronized (this) {\n            for (SubscriberMethod subscriberMethod : subscriberMethods) {\n                subscribe(subscriber, subscriberMethod);\n            }\n        }\n    }\n\n    // Must be called in synchronized block\n    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {\n        Class<?> eventType = subscriberMethod.eventType;\n        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);\n        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);\n        if (subscriptions == null) {\n            subscriptions = new CopyOnWriteArrayList<>();\n            subscriptionsByEventType.put(eventType, subscriptions);\n        } else {\n            if (subscriptions.contains(newSubscription)) {\n                throw new EventBusException(\"Subscriber \" + subscriber.getClass() + \" already registered to event \"\n                        + eventType);\n            }\n        }\n\n        int size = subscriptions.size();\n        for (int i = 0; i <= size; i++) {\n            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {\n                subscriptions.add(i, newSubscription);\n                break;\n            }\n        }\n\n        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);\n        if (subscribedEvents == null) {\n            subscribedEvents = new ArrayList<>();\n            typesBySubscriber.put(subscriber, subscribedEvents);\n        }\n        subscribedEvents.add(eventType);\n\n        if (subscriberMethod.sticky) {\n            if (eventInheritance) {\n                // Existing sticky events of all subclasses of eventType have to be considered.\n                // Note: Iterating over all events may be inefficient with lots of sticky events,\n                // thus data structure should be changed to allow a more efficient lookup\n                // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).\n                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();\n                for (Map.Entry<Class<?>, Object> entry : entries) {\n                    Class<?> candidateEventType = entry.getKey();\n                    if (eventType.isAssignableFrom(candidateEventType)) {\n                        Object stickyEvent = entry.getValue();\n                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);\n                    }\n                }\n            } else {\n                Object stickyEvent = stickyEvents.get(eventType);\n                checkPostStickyEventToSubscription(newSubscription, stickyEvent);\n            }\n        }\n    }\n\n    private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {\n        if (stickyEvent != null) {\n            // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)\n            // --> Strange corner case, which we don't take care of here.\n            postToSubscription(newSubscription, stickyEvent, isMainThread());\n        }\n    }\n\n    /**\n     * Checks if the current thread is running in the main thread.\n     * If there is no main thread support (e.g. non-Android), \"true\" is always returned. In that case MAIN thread\n     * subscribers are always called in posting thread, and BACKGROUND subscribers are always called from a background\n     * poster.\n     */\n    private boolean isMainThread() {\n        return mainThreadSupport == null || mainThreadSupport.isMainThread();\n    }\n\n    public synchronized boolean isRegistered(Object subscriber) {\n        return typesBySubscriber.containsKey(subscriber);\n    }\n\n    /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */\n    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {\n        List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);\n        if (subscriptions != null) {\n            int size = subscriptions.size();\n            for (int i = 0; i < size; i++) {\n                Subscription subscription = subscriptions.get(i);\n                if (subscription.subscriber == subscriber) {\n                    subscription.active = false;\n                    subscriptions.remove(i);\n                    i--;\n                    size--;\n                }\n            }\n        }\n    }\n\n    /** Unregisters the given subscriber from all event classes. */\n    public synchronized void unregister(Object subscriber) {\n        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);\n        if (subscribedTypes != null) {\n            for (Class<?> eventType : subscribedTypes) {\n                unsubscribeByEventType(subscriber, eventType);\n            }\n            typesBySubscriber.remove(subscriber);\n        } else {\n            logger.log(Level.WARNING, \"Subscriber to unregister was not registered before: \" + subscriber.getClass());\n        }\n    }\n\n    /** Posts the given event to the event bus. */\n    public void post(Object event) {\n        PostingThreadState postingState = currentPostingThreadState.get();\n        List<Object> eventQueue = postingState.eventQueue;\n        eventQueue.add(event);\n\n        if (!postingState.isPosting) {\n            postingState.isMainThread = isMainThread();\n            postingState.isPosting = true;\n            if (postingState.canceled) {\n                throw new EventBusException(\"Internal error. Abort state was not reset\");\n            }\n            try {\n                while (!eventQueue.isEmpty()) {\n                    postSingleEvent(eventQueue.remove(0), postingState);\n                }\n            } finally {\n                postingState.isPosting = false;\n                postingState.isMainThread = false;\n            }\n        }\n    }\n\n    /**\n     * Called from a subscriber's event handling method, further event delivery will be canceled. Subsequent\n     * subscribers\n     * won't receive the event. Events are usually canceled by higher priority subscribers (see\n     * {@link Subscribe#priority()}). Canceling is restricted to event handling methods running in posting thread\n     * {@link ThreadMode#POSTING}.\n     */\n    public void cancelEventDelivery(Object event) {\n        PostingThreadState postingState = currentPostingThreadState.get();\n        if (!postingState.isPosting) {\n            throw new EventBusException(\n                    \"This method may only be called from inside event handling methods on the posting thread\");\n        } else if (event == null) {\n            throw new EventBusException(\"Event may not be null\");\n        } else if (postingState.event != event) {\n            throw new EventBusException(\"Only the currently handled event may be aborted\");\n        } else if (postingState.subscription.subscriberMethod.threadMode != ThreadMode.POSTING) {\n            throw new EventBusException(\" event handlers may only abort the incoming event\");\n        }\n\n        postingState.canceled = true;\n    }\n\n    /**\n     * Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky\n     * event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.\n     */\n    public void postSticky(Object event) {\n        synchronized (stickyEvents) {\n            stickyEvents.put(event.getClass(), event);\n        }\n        // Should be posted after it is putted, in case the subscriber wants to remove immediately\n        post(event);\n    }\n\n    /**\n     * Gets the most recent sticky event for the given type.\n     *\n     * @see #postSticky(Object)\n     */\n    public <T> T getStickyEvent(Class<T> eventType) {\n        synchronized (stickyEvents) {\n            return eventType.cast(stickyEvents.get(eventType));\n        }\n    }\n\n    /**\n     * Remove and gets the recent sticky event for the given event type.\n     *\n     * @see #postSticky(Object)\n     */\n    public <T> T removeStickyEvent(Class<T> eventType) {\n        synchronized (stickyEvents) {\n            return eventType.cast(stickyEvents.remove(eventType));\n        }\n    }\n\n    /**\n     * Removes the sticky event if it equals to the given event.\n     *\n     * @return true if the events matched and the sticky event was removed.\n     */\n    public boolean removeStickyEvent(Object event) {\n        synchronized (stickyEvents) {\n            Class<?> eventType = event.getClass();\n            Object existingEvent = stickyEvents.get(eventType);\n            if (event.equals(existingEvent)) {\n                stickyEvents.remove(eventType);\n                return true;\n            } else {\n                return false;\n            }\n        }\n    }\n\n    /**\n     * Removes all sticky events.\n     */\n    public void removeAllStickyEvents() {\n        synchronized (stickyEvents) {\n            stickyEvents.clear();\n        }\n    }\n\n    public boolean hasSubscriberForEvent(Class<?> eventClass) {\n        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);\n        if (eventTypes != null) {\n            int countTypes = eventTypes.size();\n            for (int h = 0; h < countTypes; h++) {\n                Class<?> clazz = eventTypes.get(h);\n                CopyOnWriteArrayList<Subscription> subscriptions;\n                synchronized (this) {\n                    subscriptions = subscriptionsByEventType.get(clazz);\n                }\n                if (subscriptions != null && !subscriptions.isEmpty()) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {\n        Class<?> eventClass = event.getClass();\n        boolean subscriptionFound = false;\n        if (eventInheritance) {\n            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);\n            int countTypes = eventTypes.size();\n            for (int h = 0; h < countTypes; h++) {\n                Class<?> clazz = eventTypes.get(h);\n                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);\n            }\n        } else {\n            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);\n        }\n        if (!subscriptionFound) {\n            if (logNoSubscriberMessages) {\n                logger.log(Level.FINE, \"No subscribers registered for event \" + eventClass);\n            }\n            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&\n                    eventClass != SubscriberExceptionEvent.class) {\n                post(new NoSubscriberEvent(this, event));\n            }\n        }\n    }\n\n    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {\n        CopyOnWriteArrayList<Subscription> subscriptions;\n        synchronized (this) {\n            subscriptions = subscriptionsByEventType.get(eventClass);\n        }\n        if (subscriptions != null && !subscriptions.isEmpty()) {\n            for (Subscription subscription : subscriptions) {\n                postingState.event = event;\n                postingState.subscription = subscription;\n                boolean aborted;\n                try {\n                    postToSubscription(subscription, event, postingState.isMainThread);\n                    aborted = postingState.canceled;\n                } finally {\n                    postingState.event = null;\n                    postingState.subscription = null;\n                    postingState.canceled = false;\n                }\n                if (aborted) {\n                    break;\n                }\n            }\n            return true;\n        }\n        return false;\n    }\n\n    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {\n        switch (subscription.subscriberMethod.threadMode) {\n            case POSTING:\n                invokeSubscriber(subscription, event);\n                break;\n            case MAIN:\n                if (isMainThread) {\n                    invokeSubscriber(subscription, event);\n                } else {\n                    mainThreadPoster.enqueue(subscription, event);\n                }\n                break;\n            case MAIN_ORDERED:\n                if (mainThreadPoster != null) {\n                    mainThreadPoster.enqueue(subscription, event);\n                } else {\n                    // temporary: technically not correct as poster not decoupled from subscriber\n                    invokeSubscriber(subscription, event);\n                }\n                break;\n            case BACKGROUND:\n                if (isMainThread) {\n                    backgroundPoster.enqueue(subscription, event);\n                } else {\n                    invokeSubscriber(subscription, event);\n                }\n                break;\n            case ASYNC:\n                asyncPoster.enqueue(subscription, event);\n                break;\n            default:\n                throw new IllegalStateException(\"Unknown thread mode: \" + subscription.subscriberMethod.threadMode);\n        }\n    }\n\n    /** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */\n    private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {\n        synchronized (eventTypesCache) {\n            List<Class<?>> eventTypes = eventTypesCache.get(eventClass);\n            if (eventTypes == null) {\n                eventTypes = new ArrayList<>();\n                Class<?> clazz = eventClass;\n                while (clazz != null) {\n                    eventTypes.add(clazz);\n                    addInterfaces(eventTypes, clazz.getInterfaces());\n                    clazz = clazz.getSuperclass();\n                }\n                eventTypesCache.put(eventClass, eventTypes);\n            }\n            return eventTypes;\n        }\n    }\n\n    /** Recurses through super interfaces. */\n    static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {\n        for (Class<?> interfaceClass : interfaces) {\n            if (!eventTypes.contains(interfaceClass)) {\n                eventTypes.add(interfaceClass);\n                addInterfaces(eventTypes, interfaceClass.getInterfaces());\n            }\n        }\n    }\n\n    /**\n     * Invokes the subscriber if the subscriptions is still active. Skipping subscriptions prevents race conditions\n     * between {@link #unregister(Object)} and event delivery. Otherwise the event might be delivered after the\n     * subscriber unregistered. This is particularly important for main thread delivery and registrations bound to the\n     * live cycle of an Activity or Fragment.\n     */\n    void invokeSubscriber(PendingPost pendingPost) {\n        Object event = pendingPost.event;\n        Subscription subscription = pendingPost.subscription;\n        PendingPost.releasePendingPost(pendingPost);\n        if (subscription.active) {\n            invokeSubscriber(subscription, event);\n        }\n    }\n\n    void invokeSubscriber(Subscription subscription, Object event) {\n        try {\n            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);\n        } catch (InvocationTargetException e) {\n            handleSubscriberException(subscription, event, e.getCause());\n        } catch (IllegalAccessException e) {\n            throw new IllegalStateException(\"Unexpected exception\", e);\n        }\n    }\n\n    private void handleSubscriberException(Subscription subscription, Object event, Throwable cause) {\n        if (event instanceof SubscriberExceptionEvent) {\n            if (logSubscriberExceptions) {\n                // Don't send another SubscriberExceptionEvent to avoid infinite event recursion, just log\n                logger.log(Level.SEVERE, \"SubscriberExceptionEvent subscriber \" + subscription.subscriber.getClass()\n                        + \" threw an exception\", cause);\n                SubscriberExceptionEvent exEvent = (SubscriberExceptionEvent) event;\n                logger.log(Level.SEVERE, \"Initial event \" + exEvent.causingEvent + \" caused exception in \"\n                        + exEvent.causingSubscriber, exEvent.throwable);\n            }\n        } else {\n            if (throwSubscriberException) {\n                throw new EventBusException(\"Invoking subscriber failed\", cause);\n            }\n            if (logSubscriberExceptions) {\n                logger.log(Level.SEVERE, \"Could not dispatch event: \" + event.getClass() + \" to subscribing class \"\n                        + subscription.subscriber.getClass(), cause);\n            }\n            if (sendSubscriberExceptionEvent) {\n                SubscriberExceptionEvent exEvent = new SubscriberExceptionEvent(this, cause, event,\n                        subscription.subscriber);\n                post(exEvent);\n            }\n        }\n    }\n\n    /** For ThreadLocal, much faster to set (and get multiple values). */\n    final static class PostingThreadState {\n        final List<Object> eventQueue = new ArrayList<>();\n        boolean isPosting;\n        boolean isMainThread;\n        Subscription subscription;\n        Object event;\n        boolean canceled;\n    }\n\n    ExecutorService getExecutorService() {\n        return executorService;\n    }\n\n    /**\n     * For internal use only.\n     */\n    public Logger getLogger() {\n        return logger;\n    }\n\n    // Just an idea: we could provide a callback to post() to be notified, an alternative would be events, of course...\n    /* public */interface PostCallback {\n        void onPostCompleted(List<SubscriberExceptionEvent> exceptionEvents);\n    }\n\n    @Override\n    public String toString() {\n        return \"EventBus[indexCount=\" + indexCount + \", eventInheritance=\" + eventInheritance + \"]\";\n    }\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java",
    "content": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.greenrobot.eventbus.android.AndroidComponents;\nimport org.greenrobot.eventbus.meta.SubscriberInfoIndex;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.\n * Create a new builder using {@link EventBus#builder()}.\n */\n@SuppressWarnings(\"unused\")\npublic class EventBusBuilder {\n    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();\n\n    boolean logSubscriberExceptions = true;\n    boolean logNoSubscriberMessages = true;\n    boolean sendSubscriberExceptionEvent = true;\n    boolean sendNoSubscriberEvent = true;\n    boolean throwSubscriberException;\n    boolean eventInheritance = true;\n    boolean ignoreGeneratedIndex;\n    boolean strictMethodVerification;\n    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;\n    List<Class<?>> skipMethodVerificationForClasses;\n    List<SubscriberInfoIndex> subscriberInfoIndexes;\n    Logger logger;\n    MainThreadSupport mainThreadSupport;\n\n    EventBusBuilder() {\n    }\n\n    /** Default: true */\n    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {\n        this.logSubscriberExceptions = logSubscriberExceptions;\n        return this;\n    }\n\n    /** Default: true */\n    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {\n        this.logNoSubscriberMessages = logNoSubscriberMessages;\n        return this;\n    }\n\n    /** Default: true */\n    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {\n        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;\n        return this;\n    }\n\n    /** Default: true */\n    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {\n        this.sendNoSubscriberEvent = sendNoSubscriberEvent;\n        return this;\n    }\n\n    /**\n     * Fails if an subscriber throws an exception (default: false).\n     * <p/>\n     * Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss\n     * exceptions during development.\n     */\n    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {\n        this.throwSubscriberException = throwSubscriberException;\n        return this;\n    }\n\n    /**\n     * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).\n     * Switching this feature off will improve posting of events. For simple event classes extending Object directly,\n     * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be\n     * greater than 20%.\n     * <p/>\n     * However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,\n     * unless it is posting at high rates, e.g. hundreds/thousands of events per second.\n     */\n    public EventBusBuilder eventInheritance(boolean eventInheritance) {\n        this.eventInheritance = eventInheritance;\n        return this;\n    }\n\n\n    /**\n     * Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced\n     * setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.\n     */\n    public EventBusBuilder executorService(ExecutorService executorService) {\n        this.executorService = executorService;\n        return this;\n    }\n\n    /**\n     * Method name verification is done for methods starting with onEvent to avoid typos; using this method you can\n     * exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor\n     * abstract).\n     */\n    public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {\n        if (skipMethodVerificationForClasses == null) {\n            skipMethodVerificationForClasses = new ArrayList<>();\n        }\n        skipMethodVerificationForClasses.add(clazz);\n        return this;\n    }\n\n    /** Forces the use of reflection even if there's a generated index (default: false). */\n    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {\n        this.ignoreGeneratedIndex = ignoreGeneratedIndex;\n        return this;\n    }\n\n    /** Enables strict method verification (default: false). */\n    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {\n        this.strictMethodVerification = strictMethodVerification;\n        return this;\n    }\n\n    /** Adds an index generated by EventBus' annotation preprocessor. */\n    public EventBusBuilder addIndex(SubscriberInfoIndex index) {\n        if (subscriberInfoIndexes == null) {\n            subscriberInfoIndexes = new ArrayList<>();\n        }\n        subscriberInfoIndexes.add(index);\n        return this;\n    }\n\n    /**\n     * Set a specific log handler for all EventBus logging.\n     * <p/>\n     * By default, all logging is via {@code android.util.Log} on Android or System.out on JVM.\n     */\n    public EventBusBuilder logger(Logger logger) {\n        this.logger = logger;\n        return this;\n    }\n\n    Logger getLogger() {\n        if (logger != null) {\n            return logger;\n        } else {\n            return Logger.Default.get();\n        }\n    }\n\n    MainThreadSupport getMainThreadSupport() {\n        if (mainThreadSupport != null) {\n            return mainThreadSupport;\n        } else if (AndroidComponents.areAvailable()) {\n            return AndroidComponents.get().defaultMainThreadSupport;\n        } else {\n            return null;\n        }\n    }\n\n    /**\n     * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be\n     * done only once before the first usage of the default EventBus.\n     *\n     * @throws EventBusException if there's already a default EventBus instance in place\n     */\n    public EventBus installDefaultEventBus() {\n        synchronized (EventBus.class) {\n            if (EventBus.defaultInstance != null) {\n                throw new EventBusException(\"Default instance already exists.\" +\n                        \" It may be only set once before it's used the first time to ensure consistent behavior.\");\n            }\n            EventBus.defaultInstance = build();\n            return EventBus.defaultInstance;\n        }\n    }\n\n    /** Builds an EventBus based on the current configuration. */\n    public EventBus build() {\n        return new EventBus(this);\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/EventBusException.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\n/**\n * An {@link RuntimeException} thrown in cases something went wrong inside EventBus.\n * \n * @author Markus\n * \n */\npublic class EventBusException extends RuntimeException {\n\n    private static final long serialVersionUID = -2912559384646531479L;\n\n    public EventBusException(String detailMessage) {\n        super(detailMessage);\n    }\n\n    public EventBusException(Throwable throwable) {\n        super(throwable);\n    }\n\n    public EventBusException(String detailMessage, Throwable throwable) {\n        super(detailMessage, throwable);\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Logger.java",
    "content": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.greenrobot.eventbus.android.AndroidComponents;\nimport java.util.logging.Level;\n\npublic interface Logger {\n\n    void log(Level level, String msg);\n\n    void log(Level level, String msg, Throwable th);\n\n    class JavaLogger implements Logger {\n        protected final java.util.logging.Logger logger;\n\n        public JavaLogger(String tag) {\n            logger = java.util.logging.Logger.getLogger(tag);\n        }\n\n        @Override\n        public void log(Level level, String msg) {\n            // TODO Replace logged method with caller method\n            logger.log(level, msg);\n        }\n\n        @Override\n        public void log(Level level, String msg, Throwable th) {\n            // TODO Replace logged method with caller method\n            logger.log(level, msg, th);\n        }\n\n    }\n\n    class SystemOutLogger implements Logger {\n\n        @Override\n        public void log(Level level, String msg) {\n            System.out.println(\"[\" + level + \"] \" + msg);\n        }\n\n        @Override\n        public void log(Level level, String msg, Throwable th) {\n            System.out.println(\"[\" + level + \"] \" + msg);\n            th.printStackTrace(System.out);\n        }\n\n    }\n\n    class Default {\n        public static Logger get() {\n            if (AndroidComponents.areAvailable()) {\n                return AndroidComponents.get().logger;\n            }\n\n            return new SystemOutLogger();\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\n/**\n * Interface to the \"main\" thread, which can be whatever you like. Typically on Android, Android's main thread is used.\n */\npublic interface MainThreadSupport {\n\n    boolean isMainThread();\n\n    Poster createPoster(EventBus eventBus);\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/NoSubscriberEvent.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\n/**\n * This Event is posted by EventBus when no subscriber is found for a posted event.\n * \n * @author Markus\n */\npublic final class NoSubscriberEvent {\n    /** The {@link EventBus} instance to with the original event was posted to. */\n    public final EventBus eventBus;\n\n    /** The original event that could not be delivered to any subscriber. */\n    public final Object originalEvent;\n\n    public NoSubscriberEvent(EventBus eventBus, Object originalEvent) {\n        this.eventBus = eventBus;\n        this.originalEvent = originalEvent;\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/PendingPost.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nfinal class PendingPost {\n    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();\n\n    Object event;\n    Subscription subscription;\n    PendingPost next;\n\n    private PendingPost(Object event, Subscription subscription) {\n        this.event = event;\n        this.subscription = subscription;\n    }\n\n    static PendingPost obtainPendingPost(Subscription subscription, Object event) {\n        synchronized (pendingPostPool) {\n            int size = pendingPostPool.size();\n            if (size > 0) {\n                PendingPost pendingPost = pendingPostPool.remove(size - 1);\n                pendingPost.event = event;\n                pendingPost.subscription = subscription;\n                pendingPost.next = null;\n                return pendingPost;\n            }\n        }\n        return new PendingPost(event, subscription);\n    }\n\n    static void releasePendingPost(PendingPost pendingPost) {\n        pendingPost.event = null;\n        pendingPost.subscription = null;\n        pendingPost.next = null;\n        synchronized (pendingPostPool) {\n            // Don't let the pool grow indefinitely\n            if (pendingPostPool.size() < 10000) {\n                pendingPostPool.add(pendingPost);\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/PendingPostQueue.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus;\n\nfinal class PendingPostQueue {\n    private PendingPost head;\n    private PendingPost tail;\n\n    synchronized void enqueue(PendingPost pendingPost) {\n        if (pendingPost == null) {\n            throw new NullPointerException(\"null cannot be enqueued\");\n        }\n        if (tail != null) {\n            tail.next = pendingPost;\n            tail = pendingPost;\n        } else if (head == null) {\n            head = tail = pendingPost;\n        } else {\n            throw new IllegalStateException(\"Head present, but no tail\");\n        }\n        notifyAll();\n    }\n\n    synchronized PendingPost poll() {\n        PendingPost pendingPost = head;\n        if (head != null) {\n            head = head.next;\n            if (head == null) {\n                tail = null;\n            }\n        }\n        return pendingPost;\n    }\n\n    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {\n        if (head == null) {\n            wait(maxMillisToWait);\n        }\n        return poll();\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Poster.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\n/**\n * Posts events.\n *\n * @author William Ferguson\n */\npublic interface Poster {\n\n    /**\n     * Enqueue an event to be posted for a particular subscription.\n     *\n     * @param subscription Subscription which will receive the event.\n     * @param event        Event that will be posted to subscribers.\n     */\n    void enqueue(Subscription subscription, Object event);\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Subscribe.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus;\n\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.METHOD})\npublic @interface Subscribe {\n    ThreadMode threadMode() default ThreadMode.POSTING;\n\n    /**\n     * If true, delivers the most recent sticky event (posted with\n     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).\n     */\n    boolean sticky() default false;\n\n    /** Subscriber priority to influence the order of event delivery.\n     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before\n     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of\n     * delivery among subscribers with different {@link ThreadMode}s! */\n    int priority() default 0;\n}\n\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/SubscriberExceptionEvent.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\n/**\n * This Event is posted by EventBus when an exception occurs inside a subscriber's event handling method.\n * \n * @author Markus\n */\npublic final class SubscriberExceptionEvent {\n    /** The {@link EventBus} instance to with the original event was posted to. */\n    public final EventBus eventBus;\n\n    /** The Throwable thrown by a subscriber. */\n    public final Throwable throwable;\n\n    /** The original event that could not be delivered to any subscriber. */\n    public final Object causingEvent;\n\n    /** The subscriber that threw the Throwable. */\n    public final Object causingSubscriber;\n\n    public SubscriberExceptionEvent(EventBus eventBus, Throwable throwable, Object causingEvent,\n            Object causingSubscriber) {\n        this.eventBus = eventBus;\n        this.throwable = throwable;\n        this.causingEvent = causingEvent;\n        this.causingSubscriber = causingSubscriber;\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/SubscriberMethod.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport java.lang.reflect.Method;\n\n/** Used internally by EventBus and generated subscriber indexes. */\npublic class SubscriberMethod {\n    final Method method;\n    final ThreadMode threadMode;\n    final Class<?> eventType;\n    final int priority;\n    final boolean sticky;\n    /** Used for efficient comparison */\n    String methodString;\n\n    public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {\n        this.method = method;\n        this.threadMode = threadMode;\n        this.eventType = eventType;\n        this.priority = priority;\n        this.sticky = sticky;\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) {\n            return true;\n        } else if (other instanceof SubscriberMethod) {\n            checkMethodString();\n            SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;\n            otherSubscriberMethod.checkMethodString();\n            // Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6\n            return methodString.equals(otherSubscriberMethod.methodString);\n        } else {\n            return false;\n        }\n    }\n\n    private synchronized void checkMethodString() {\n        if (methodString == null) {\n            // Method.toString has more overhead, just take relevant parts of the method\n            StringBuilder builder = new StringBuilder(64);\n            builder.append(method.getDeclaringClass().getName());\n            builder.append('#').append(method.getName());\n            builder.append('(').append(eventType.getName());\n            methodString = builder.toString();\n        }\n    }\n\n    @Override\n    public int hashCode() {\n        return method.hashCode();\n    }\n}"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.greenrobot.eventbus.meta.SubscriberInfo;\nimport org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nclass SubscriberMethodFinder {\n    /*\n     * In newer class files, compilers may add methods. Those are called bridge or synthetic methods.\n     * EventBus must ignore both. There modifiers are not public but defined in the Java class file format:\n     * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6-200-A.1\n     */\n    private static final int BRIDGE = 0x40;\n    private static final int SYNTHETIC = 0x1000;\n\n    private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;\n    private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();\n\n    private List<SubscriberInfoIndex> subscriberInfoIndexes;\n    private final boolean strictMethodVerification;\n    private final boolean ignoreGeneratedIndex;\n\n    private static final int POOL_SIZE = 4;\n    private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];\n\n    SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,\n                           boolean ignoreGeneratedIndex) {\n        this.subscriberInfoIndexes = subscriberInfoIndexes;\n        this.strictMethodVerification = strictMethodVerification;\n        this.ignoreGeneratedIndex = ignoreGeneratedIndex;\n    }\n\n    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {\n        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);\n        if (subscriberMethods != null) {\n            return subscriberMethods;\n        }\n\n        if (ignoreGeneratedIndex) {\n            subscriberMethods = findUsingReflection(subscriberClass);\n        } else {\n            subscriberMethods = findUsingInfo(subscriberClass);\n        }\n        if (subscriberMethods.isEmpty()) {\n            throw new EventBusException(\"Subscriber \" + subscriberClass\n                    + \" and its super classes have no public methods with the @Subscribe annotation\");\n        } else {\n            METHOD_CACHE.put(subscriberClass, subscriberMethods);\n            return subscriberMethods;\n        }\n    }\n\n    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {\n        FindState findState = prepareFindState();\n        findState.initForSubscriber(subscriberClass);\n        while (findState.clazz != null) {\n            findState.subscriberInfo = getSubscriberInfo(findState);\n            if (findState.subscriberInfo != null) {\n                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();\n                for (SubscriberMethod subscriberMethod : array) {\n                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {\n                        findState.subscriberMethods.add(subscriberMethod);\n                    }\n                }\n            } else {\n                findUsingReflectionInSingleClass(findState);\n            }\n            findState.moveToSuperclass();\n        }\n        return getMethodsAndRelease(findState);\n    }\n\n    private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {\n        List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);\n        findState.recycle();\n        synchronized (FIND_STATE_POOL) {\n            for (int i = 0; i < POOL_SIZE; i++) {\n                if (FIND_STATE_POOL[i] == null) {\n                    FIND_STATE_POOL[i] = findState;\n                    break;\n                }\n            }\n        }\n        return subscriberMethods;\n    }\n\n    private FindState prepareFindState() {\n        synchronized (FIND_STATE_POOL) {\n            for (int i = 0; i < POOL_SIZE; i++) {\n                FindState state = FIND_STATE_POOL[i];\n                if (state != null) {\n                    FIND_STATE_POOL[i] = null;\n                    return state;\n                }\n            }\n        }\n        return new FindState();\n    }\n\n    private SubscriberInfo getSubscriberInfo(FindState findState) {\n        if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {\n            SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();\n            if (findState.clazz == superclassInfo.getSubscriberClass()) {\n                return superclassInfo;\n            }\n        }\n        if (subscriberInfoIndexes != null) {\n            for (SubscriberInfoIndex index : subscriberInfoIndexes) {\n                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);\n                if (info != null) {\n                    return info;\n                }\n            }\n        }\n        return null;\n    }\n\n    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {\n        FindState findState = prepareFindState();\n        findState.initForSubscriber(subscriberClass);\n        while (findState.clazz != null) {\n            findUsingReflectionInSingleClass(findState);\n            findState.moveToSuperclass();\n        }\n        return getMethodsAndRelease(findState);\n    }\n\n    private void findUsingReflectionInSingleClass(FindState findState) {\n        Method[] methods;\n        try {\n            // This is faster than getMethods, especially when subscribers are fat classes like Activities\n            methods = findState.clazz.getDeclaredMethods();\n        } catch (Throwable th) {\n            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149\n            try {\n                methods = findState.clazz.getMethods();\n            } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...\n                String msg = \"Could not inspect methods of \" + findState.clazz.getName();\n                if (ignoreGeneratedIndex) {\n                    msg += \". Please consider using EventBus annotation processor to avoid reflection.\";\n                } else {\n                    msg += \". Please make this class visible to EventBus annotation processor to avoid reflection.\";\n                }\n                throw new EventBusException(msg, error);\n            }\n            findState.skipSuperClasses = true;\n        }\n        for (Method method : methods) {\n            int modifiers = method.getModifiers();\n            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {\n                Class<?>[] parameterTypes = method.getParameterTypes();\n                if (parameterTypes.length == 1) {\n                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);\n                    if (subscribeAnnotation != null) {\n                        Class<?> eventType = parameterTypes[0];\n                        if (findState.checkAdd(method, eventType)) {\n                            ThreadMode threadMode = subscribeAnnotation.threadMode();\n                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,\n                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));\n                        }\n                    }\n                } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {\n                    String methodName = method.getDeclaringClass().getName() + \".\" + method.getName();\n                    throw new EventBusException(\"@Subscribe method \" + methodName +\n                            \"must have exactly 1 parameter but has \" + parameterTypes.length);\n                }\n            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {\n                String methodName = method.getDeclaringClass().getName() + \".\" + method.getName();\n                throw new EventBusException(methodName +\n                        \" is a illegal @Subscribe method: must be public, non-static, and non-abstract\");\n            }\n        }\n    }\n\n    static void clearCaches() {\n        METHOD_CACHE.clear();\n    }\n\n    static class FindState {\n        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();\n        final Map<Class, Object> anyMethodByEventType = new HashMap<>();\n        final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();\n        final StringBuilder methodKeyBuilder = new StringBuilder(128);\n\n        Class<?> subscriberClass;\n        Class<?> clazz;\n        boolean skipSuperClasses;\n        SubscriberInfo subscriberInfo;\n\n        void initForSubscriber(Class<?> subscriberClass) {\n            this.subscriberClass = clazz = subscriberClass;\n            skipSuperClasses = false;\n            subscriberInfo = null;\n        }\n\n        void recycle() {\n            subscriberMethods.clear();\n            anyMethodByEventType.clear();\n            subscriberClassByMethodKey.clear();\n            methodKeyBuilder.setLength(0);\n            subscriberClass = null;\n            clazz = null;\n            skipSuperClasses = false;\n            subscriberInfo = null;\n        }\n\n        boolean checkAdd(Method method, Class<?> eventType) {\n            // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.\n            // Usually a subscriber doesn't have methods listening to the same event type.\n            Object existing = anyMethodByEventType.put(eventType, method);\n            if (existing == null) {\n                return true;\n            } else {\n                if (existing instanceof Method) {\n                    if (!checkAddWithMethodSignature((Method) existing, eventType)) {\n                        // Paranoia check\n                        throw new IllegalStateException();\n                    }\n                    // Put any non-Method object to \"consume\" the existing Method\n                    anyMethodByEventType.put(eventType, this);\n                }\n                return checkAddWithMethodSignature(method, eventType);\n            }\n        }\n\n        private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {\n            methodKeyBuilder.setLength(0);\n            methodKeyBuilder.append(method.getName());\n            methodKeyBuilder.append('>').append(eventType.getName());\n\n            String methodKey = methodKeyBuilder.toString();\n            Class<?> methodClass = method.getDeclaringClass();\n            Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);\n            if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {\n                // Only add if not already found in a sub class\n                return true;\n            } else {\n                // Revert the put, old class is further down the class hierarchy\n                subscriberClassByMethodKey.put(methodKey, methodClassOld);\n                return false;\n            }\n        }\n\n        void moveToSuperclass() {\n            if (skipSuperClasses) {\n                clazz = null;\n            } else {\n                clazz = clazz.getSuperclass();\n                String clazzName = clazz.getName();\n                // Skip system classes, this degrades performance.\n                // Also we might avoid some ClassNotFoundException (see FAQ for background).\n                if (clazzName.startsWith(\"java.\") || clazzName.startsWith(\"javax.\") ||\n                        clazzName.startsWith(\"android.\") || clazzName.startsWith(\"androidx.\")) {\n                    clazz = null;\n                }\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Subscription.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nfinal class Subscription {\n    final Object subscriber;\n    final SubscriberMethod subscriberMethod;\n    /**\n     * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery\n     * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.\n     */\n    volatile boolean active;\n\n    Subscription(Object subscriber, SubscriberMethod subscriberMethod) {\n        this.subscriber = subscriber;\n        this.subscriberMethod = subscriberMethod;\n        active = true;\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if (other instanceof Subscription) {\n            Subscription otherSubscription = (Subscription) other;\n            return subscriber == otherSubscription.subscriber\n                    && subscriberMethod.equals(otherSubscription.subscriberMethod);\n        } else {\n            return false;\n        }\n    }\n\n    @Override\n    public int hashCode() {\n        return subscriber.hashCode() + subscriberMethod.methodString.hashCode();\n    }\n}"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/ThreadMode.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\n/**\n * Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus.\n * EventBus takes care of threading independently of the posting thread.\n *\n * @see EventBus#register(Object)\n */\npublic enum ThreadMode {\n    /**\n     * This is the default. Subscriber will be called directly in the same thread, which is posting the event. Event delivery\n     * implies the least overhead because it avoids thread switching completely. Thus, this is the recommended mode for\n     * simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers\n     * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.\n     */\n    POSTING,\n\n    /**\n     * On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is\n     * the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event\n     * is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.\n     * <p>\n     * If not on Android, behaves the same as {@link #POSTING}.\n     */\n    MAIN,\n\n    /**\n     * On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},\n     * the event will always be queued for delivery. This ensures that the post call is non-blocking.\n     * <p>\n     * If not on Android, behaves the same as {@link #POSTING}.\n     */\n    MAIN_ORDERED,\n\n    /**\n     * On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods\n     * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single\n     * background thread, that will deliver all its events sequentially. Subscribers using this mode should try to\n     * return quickly to avoid blocking the background thread.\n     * <p>\n     * If not on Android, always uses a background thread.\n     */\n    BACKGROUND,\n\n    /**\n     * Subscriber will be called in a separate thread. This is always independent of the posting thread and the\n     * main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should\n     * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number\n     * of long-running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus\n     * uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.\n     */\n    ASYNC\n}"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java",
    "content": "package org.greenrobot.eventbus.android;\n\nimport org.greenrobot.eventbus.Logger;\nimport org.greenrobot.eventbus.MainThreadSupport;\n\npublic abstract class AndroidComponents {\n\n    private static final AndroidComponents implementation;\n\n    static {\n        implementation = AndroidDependenciesDetector.isAndroidSDKAvailable()\n            ? AndroidDependenciesDetector.instantiateAndroidComponents()\n            : null;\n    }\n\n    public static boolean areAvailable() {\n        return implementation != null;\n    }\n\n    public static AndroidComponents get() {\n        return implementation;\n    }\n\n    public final Logger logger;\n    public final MainThreadSupport defaultMainThreadSupport;\n\n    public AndroidComponents(Logger logger, MainThreadSupport defaultMainThreadSupport) {\n        this.logger = logger;\n        this.defaultMainThreadSupport = defaultMainThreadSupport;\n    }\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java",
    "content": "package org.greenrobot.eventbus.android;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\n@SuppressWarnings(\"TryWithIdenticalCatches\")\npublic class AndroidDependenciesDetector {\n\n    public static boolean isAndroidSDKAvailable() {\n\n        try {\n            Class<?> looperClass = Class.forName(\"android.os.Looper\");\n            Method getMainLooper = looperClass.getDeclaredMethod(\"getMainLooper\");\n            Object mainLooper = getMainLooper.invoke(null);\n            return mainLooper != null;\n        }\n        catch (ClassNotFoundException ignored) {}\n        catch (NoSuchMethodException ignored) {}\n        catch (IllegalAccessException ignored) {}\n        catch (InvocationTargetException ignored) {}\n\n        return false;\n    }\n\n    private static final String ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME = \"org.greenrobot.eventbus.android.AndroidComponentsImpl\";\n\n    public static boolean areAndroidComponentsAvailable() {\n\n        try {\n            Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);\n            return true;\n        }\n        catch (ClassNotFoundException ex) {\n            return false;\n        }\n    }\n\n    public static AndroidComponents instantiateAndroidComponents() {\n\n        try {\n            Class<?> impl = Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);\n            return (AndroidComponents) impl.getConstructor().newInstance();\n        }\n        catch (Throwable ex) {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.meta;\n\nimport org.greenrobot.eventbus.EventBusException;\nimport org.greenrobot.eventbus.SubscriberMethod;\nimport org.greenrobot.eventbus.ThreadMode;\n\nimport java.lang.reflect.Method;\n\n/** Base class for generated subscriber meta info classes created by annotation processing. */\npublic abstract class AbstractSubscriberInfo implements SubscriberInfo {\n    private final Class subscriberClass;\n    private final Class<? extends SubscriberInfo> superSubscriberInfoClass;\n    private final boolean shouldCheckSuperclass;\n\n    protected AbstractSubscriberInfo(Class subscriberClass, Class<? extends SubscriberInfo> superSubscriberInfoClass,\n                                     boolean shouldCheckSuperclass) {\n        this.subscriberClass = subscriberClass;\n        this.superSubscriberInfoClass = superSubscriberInfoClass;\n        this.shouldCheckSuperclass = shouldCheckSuperclass;\n    }\n\n    @Override\n    public Class getSubscriberClass() {\n        return subscriberClass;\n    }\n\n    @Override\n    public SubscriberInfo getSuperSubscriberInfo() {\n        if(superSubscriberInfoClass == null) {\n            return null;\n        }\n        try {\n            return superSubscriberInfoClass.newInstance();\n        } catch (InstantiationException e) {\n            throw new RuntimeException(e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    @Override\n    public boolean shouldCheckSuperclass() {\n        return shouldCheckSuperclass;\n    }\n\n    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType) {\n        return createSubscriberMethod(methodName, eventType, ThreadMode.POSTING, 0, false);\n    }\n\n    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode) {\n        return createSubscriberMethod(methodName, eventType, threadMode, 0, false);\n    }\n\n    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,\n                                                      int priority, boolean sticky) {\n        try {\n            Method method = subscriberClass.getDeclaredMethod(methodName, eventType);\n            return new SubscriberMethod(method, eventType, threadMode, priority, sticky);\n        } catch (NoSuchMethodException e) {\n            throw new EventBusException(\"Could not find subscriber method in \" + subscriberClass +\n                    \". Maybe a missing ProGuard rule?\", e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SimpleSubscriberInfo.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.meta;\n\nimport org.greenrobot.eventbus.SubscriberMethod;\n\n/**\n * Uses {@link SubscriberMethodInfo} objects to create {@link org.greenrobot.eventbus.SubscriberMethod} objects on demand.\n */\npublic class SimpleSubscriberInfo extends AbstractSubscriberInfo {\n\n    private final SubscriberMethodInfo[] methodInfos;\n\n    public SimpleSubscriberInfo(Class subscriberClass, boolean shouldCheckSuperclass, SubscriberMethodInfo[] methodInfos) {\n        super(subscriberClass, null, shouldCheckSuperclass);\n        this.methodInfos = methodInfos;\n    }\n\n    @Override\n    public synchronized SubscriberMethod[] getSubscriberMethods() {\n        int length = methodInfos.length;\n        SubscriberMethod[] methods = new SubscriberMethod[length];\n        for (int i = 0; i < length; i++) {\n            SubscriberMethodInfo info = methodInfos[i];\n            methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,\n                    info.priority, info.sticky);\n        }\n        return methods;\n    }\n}"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfo.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.meta;\n\nimport org.greenrobot.eventbus.SubscriberMethod;\n\n/** Base class for generated index classes created by annotation processing. */\npublic interface SubscriberInfo {\n    Class<?> getSubscriberClass();\n\n    SubscriberMethod[] getSubscriberMethods();\n\n    SubscriberInfo getSuperSubscriberInfo();\n\n    boolean shouldCheckSuperclass();\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfoIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.meta;\n\n/**\n * Interface for generated indexes.\n */\npublic interface SubscriberInfoIndex {\n    SubscriberInfo getSubscriberInfo(Class<?> subscriberClass);\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SubscriberMethodInfo.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.meta;\n\nimport org.greenrobot.eventbus.ThreadMode;\n\npublic class SubscriberMethodInfo {\n    final String methodName;\n    final ThreadMode threadMode;\n    final Class<?> eventType;\n    final int priority;\n    final boolean sticky;\n\n    public SubscriberMethodInfo(String methodName, Class<?> eventType, ThreadMode threadMode,\n                                int priority, boolean sticky) {\n        this.methodName = methodName;\n        this.threadMode = threadMode;\n        this.eventType = eventType;\n        this.priority = priority;\n        this.sticky = sticky;\n    }\n\n    public SubscriberMethodInfo(String methodName, Class<?> eventType) {\n        this(methodName, eventType, ThreadMode.POSTING, 0, false);\n    }\n\n    public SubscriberMethodInfo(String methodName, Class<?> eventType, ThreadMode threadMode) {\n        this(methodName, eventType, threadMode, 0, false);\n    }\n\n}"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.util;\n\nimport org.greenrobot.eventbus.EventBus;\n\nimport java.lang.reflect.Constructor;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\nimport java.util.logging.Level;\n\n/**\n * Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting failure events.\n * By default, uses {@link ThrowableFailureEvent}.\n * <p>\n * Set a custom event type using {@link Builder#failureEventType(Class)}.\n * The failure event class must have a constructor with one parameter of type {@link Throwable}.\n * If using ProGuard or R8 make sure the constructor of the failure event class is kept, it is accessed via reflection.\n * E.g. add a rule like\n * <pre>\n * -keepclassmembers class com.example.CustomThrowableFailureEvent {\n *     &lt;init&gt;(java.lang.Throwable);\n * }\n * </pre>\n */\npublic class AsyncExecutor {\n\n    public static class Builder {\n        private Executor threadPool;\n        private Class<?> failureEventType;\n        private EventBus eventBus;\n\n        private Builder() {\n        }\n\n        public Builder threadPool(Executor threadPool) {\n            this.threadPool = threadPool;\n            return this;\n        }\n\n        public Builder failureEventType(Class<?> failureEventType) {\n            this.failureEventType = failureEventType;\n            return this;\n        }\n\n        public Builder eventBus(EventBus eventBus) {\n            this.eventBus = eventBus;\n            return this;\n        }\n\n        public AsyncExecutor build() {\n            return buildForScope(null);\n        }\n\n        public AsyncExecutor buildForScope(Object executionContext) {\n            if (eventBus == null) {\n                eventBus = EventBus.getDefault();\n            }\n            if (threadPool == null) {\n                threadPool = Executors.newCachedThreadPool();\n            }\n            if (failureEventType == null) {\n                failureEventType = ThrowableFailureEvent.class;\n            }\n            return new AsyncExecutor(threadPool, eventBus, failureEventType, executionContext);\n        }\n    }\n\n    /** Like {@link Runnable}, but the run method may throw an exception. */\n    public interface RunnableEx {\n        void run() throws Exception;\n    }\n\n    public static Builder builder() {\n        return new Builder();\n    }\n\n    public static AsyncExecutor create() {\n        return new Builder().build();\n    }\n\n    private final Executor threadPool;\n    private final Constructor<?> failureEventConstructor;\n    private final EventBus eventBus;\n    private final Object scope;\n\n    private AsyncExecutor(Executor threadPool, EventBus eventBus, Class<?> failureEventType, Object scope) {\n        this.threadPool = threadPool;\n        this.eventBus = eventBus;\n        this.scope = scope;\n        try {\n            failureEventConstructor = failureEventType.getConstructor(Throwable.class);\n        } catch (NoSuchMethodException e) {\n            throw new RuntimeException(\n                    \"Failure event class must have a constructor with one parameter of type Throwable\", e);\n        }\n    }\n\n    /** Posts an failure event if the given {@link RunnableEx} throws an Exception. */\n    public void execute(final RunnableEx runnable) {\n        threadPool.execute(() -> {\n            try {\n                runnable.run();\n            } catch (Exception e) {\n                Object event;\n                try {\n                    event = failureEventConstructor.newInstance(e);\n                } catch (Exception e1) {\n                    eventBus.getLogger().log(Level.SEVERE, \"Original exception:\", e);\n                    throw new RuntimeException(\"Could not create failure event\", e1);\n                }\n                if (event instanceof HasExecutionScope) {\n                    ((HasExecutionScope) event).setExecutionScope(scope);\n                }\n                eventBus.post(event);\n            }\n        });\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java",
    "content": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.util;\n\nimport org.greenrobot.eventbus.Logger;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.logging.Level;\n\n\n/**\n * Maps throwables to texts for error dialogs. Use Config to configure the mapping.\n * \n * @author Markus\n */\npublic class ExceptionToResourceMapping {\n\n    public final Map<Class<? extends Throwable>, Integer> throwableToMsgIdMap;\n\n    public ExceptionToResourceMapping() {\n        throwableToMsgIdMap = new HashMap<>();\n    }\n\n    /** Looks at the exception and its causes trying to find an ID. */\n    public Integer mapThrowable(final Throwable throwable) {\n        Throwable throwableToCheck = throwable;\n        int depthToGo = 20;\n\n        while (true) {\n            Integer resId = mapThrowableFlat(throwableToCheck);\n            if (resId != null) {\n                return resId;\n            } else {\n                throwableToCheck = throwableToCheck.getCause();\n                depthToGo--;\n                if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) {\n                    Logger logger = Logger.Default.get();  // No EventBus instance here\n                    logger.log(Level.FINE, \"No specific message resource ID found for \" + throwable);\n                    // return config.defaultErrorMsgId;\n                    return null;\n                }\n            }\n        }\n\n    }\n\n    /** Mapping without checking the cause (done in mapThrowable). */\n    protected Integer mapThrowableFlat(Throwable throwable) {\n        Class<? extends Throwable> throwableClass = throwable.getClass();\n        Integer resId = throwableToMsgIdMap.get(throwableClass);\n        if (resId == null) {\n            Class<? extends Throwable> closestClass = null;\n            Set<Entry<Class<? extends Throwable>, Integer>> mappings = throwableToMsgIdMap.entrySet();\n            for (Entry<Class<? extends Throwable>, Integer> mapping : mappings) {\n                Class<? extends Throwable> candidate = mapping.getKey();\n                if (candidate.isAssignableFrom(throwableClass)) {\n                    if (closestClass == null || closestClass.isAssignableFrom(candidate)) {\n                        closestClass = candidate;\n                        resId = mapping.getValue();\n                    }\n                }\n            }\n\n        }\n        return resId;\n    }\n\n    public ExceptionToResourceMapping addMapping(Class<? extends Throwable> clazz, int msgId) {\n        throwableToMsgIdMap.put(clazz, msgId);\n        return this;\n    }\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/HasExecutionScope.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.util;\n\npublic interface HasExecutionScope {\n    Object getExecutionScope();\n\n    void setExecutionScope(Object executionScope);\n\n}\n"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.util;\n\n/**\n * A generic failure event, which can be used by apps to propagate thrown exceptions.\n * Used as default failure event by {@link AsyncExecutor}.\n */\npublic class ThrowableFailureEvent implements HasExecutionScope {\n    protected final Throwable throwable;\n    protected final boolean suppressErrorUi;\n    private Object executionContext;\n\n    public ThrowableFailureEvent(Throwable throwable) {\n        this.throwable = throwable;\n        suppressErrorUi = false;\n    }\n\n    /**\n     * @param suppressErrorUi\n     *            true indicates to the receiver that no error UI (e.g. dialog) should now displayed.\n     */\n    public ThrowableFailureEvent(Throwable throwable, boolean suppressErrorUi) {\n        this.throwable = throwable;\n        this.suppressErrorUi = suppressErrorUi;\n    }\n\n    public Throwable getThrowable() {\n        return throwable;\n    }\n\n    public boolean isSuppressErrorUi() {\n        return suppressErrorUi;\n    }\n\n    public Object getExecutionScope() {\n        return executionContext;\n    }\n\n    public void setExecutionScope(Object executionContext) {\n        this.executionContext = executionContext;\n    }\n    \n}\n"
  },
  {
    "path": "EventBusAnnotationProcessor/build.gradle",
    "content": "apply plugin: 'java'\n\ngroup = rootProject.group\nversion = rootProject.version\n\njava.sourceCompatibility = JavaVersion.VERSION_1_8\njava.targetCompatibility = JavaVersion.VERSION_1_8\n\ndependencies {\n    implementation project(':eventbus-java')\n    implementation 'de.greenrobot:java-common:2.3.1'\n\n    // Generates the required META-INF descriptor to make the processor incremental.\n    def incap = '0.2'\n    compileOnly \"net.ltgt.gradle.incap:incap:$incap\"\n    annotationProcessor \"net.ltgt.gradle.incap:incap-processor:$incap\"\n}\n\nsourceSets {\n    main {\n        java {\n            srcDir 'src'\n        }\n        resources {\n            srcDir 'res'\n        }\n    }\n}\n\njavadoc {\n    title = \"EventBus Annotation Processor ${version} API\"\n\toptions.bottom = 'Available under the Apache License, Version 2.0 - <i>Copyright &#169; 2015-2020 <a href=\"https://greenrobot.org\">greenrobot.org</a>. All Rights Reserved.</i>'\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    archiveClassifier.set(\"javadoc\")\n    from 'build/docs/javadoc'\n}\n\ntask sourcesJar(type: Jar) {\n    archiveClassifier.set(\"sources\")\n    from sourceSets.main.allSource\n}\n\napply from: rootProject.file(\"gradle/publish.gradle\")\n// Set project-specific properties\nafterEvaluate {\n    publishing.publications {\n        mavenJava(MavenPublication) {\n            artifactId = \"eventbus-annotation-processor\"\n\n            from components.java\n            artifact javadocJar\n            artifact sourcesJar\n            pom {\n                name = \"EventBus Annotation Processor\"\n                description = \"Precompiler for EventBus Annotations.\"\n                packaging = \"jar\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "EventBusAnnotationProcessor/res/META-INF/services/javax.annotation.processing.Processor",
    "content": "org.greenrobot.eventbus.annotationprocessor.EventBusAnnotationProcessor\n"
  },
  {
    "path": "EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.annotationprocessor;\n\nimport net.ltgt.gradle.incap.IncrementalAnnotationProcessor;\n\nimport org.greenrobot.eventbus.Subscribe;\nimport org.greenrobot.eventbus.ThreadMode;\n\nimport java.io.BufferedWriter;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport javax.annotation.processing.AbstractProcessor;\nimport javax.annotation.processing.Messager;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.annotation.processing.SupportedAnnotationTypes;\nimport javax.annotation.processing.SupportedOptions;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.PackageElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.TypeKind;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.type.TypeVariable;\nimport javax.tools.Diagnostic;\nimport javax.tools.JavaFileObject;\n\nimport de.greenrobot.common.ListMap;\n\n\nimport static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING;\n\n/**\n * Is an aggregating processor as it writes a single file, the subscriber index file,\n * based on found elements with the @Subscriber annotation.\n */\n@SupportedAnnotationTypes(\"org.greenrobot.eventbus.Subscribe\")\n@SupportedOptions(value = {\"eventBusIndex\", \"verbose\"})\n@IncrementalAnnotationProcessor(AGGREGATING)\npublic class EventBusAnnotationProcessor extends AbstractProcessor {\n    public static final String OPTION_EVENT_BUS_INDEX = \"eventBusIndex\";\n    public static final String OPTION_VERBOSE = \"verbose\";\n\n    /** Found subscriber methods for a class (without superclasses). */\n    private final ListMap<TypeElement, ExecutableElement> methodsByClass = new ListMap<>();\n    private final Set<TypeElement> classesToSkip = new HashSet<>();\n\n    private boolean writerRoundDone;\n    private int round;\n    private boolean verbose;\n\n    @Override\n    public SourceVersion getSupportedSourceVersion() {\n        return SourceVersion.latest();\n    }\n\n    @Override\n    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {\n        Messager messager = processingEnv.getMessager();\n        try {\n            String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);\n            if (index == null) {\n                messager.printMessage(Diagnostic.Kind.ERROR, \"No option \" + OPTION_EVENT_BUS_INDEX +\n                        \" passed to annotation processor\");\n                return false;\n            }\n            verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));\n            int lastPeriod = index.lastIndexOf('.');\n            String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;\n\n            round++;\n            if (verbose) {\n                messager.printMessage(Diagnostic.Kind.NOTE, \"Processing round \" + round + \", new annotations: \" +\n                        !annotations.isEmpty() + \", processingOver: \" + env.processingOver());\n            }\n            if (env.processingOver()) {\n                if (!annotations.isEmpty()) {\n                    messager.printMessage(Diagnostic.Kind.ERROR,\n                            \"Unexpected processing state: annotations still available after processing over\");\n                    return false;\n                }\n            }\n            if (annotations.isEmpty()) {\n                return false;\n            }\n\n            if (writerRoundDone) {\n                messager.printMessage(Diagnostic.Kind.ERROR,\n                        \"Unexpected processing state: annotations still available after writing.\");\n            }\n            collectSubscribers(annotations, env, messager);\n            checkForSubscribersToSkip(messager, indexPackage);\n\n            if (!methodsByClass.isEmpty()) {\n                createInfoIndexFile(index);\n            } else {\n                messager.printMessage(Diagnostic.Kind.WARNING, \"No @Subscribe annotations found\");\n            }\n            writerRoundDone = true;\n        } catch (RuntimeException e) {\n            // IntelliJ does not handle exceptions nicely, so log and print a message\n            e.printStackTrace();\n            messager.printMessage(Diagnostic.Kind.ERROR, \"Unexpected error in EventBusAnnotationProcessor: \" + e);\n        }\n        return true;\n    }\n\n    private void collectSubscribers(Set<? extends TypeElement> annotations, RoundEnvironment env, Messager messager) {\n        for (TypeElement annotation : annotations) {\n            Set<? extends Element> elements = env.getElementsAnnotatedWith(annotation);\n            for (Element element : elements) {\n                if (element instanceof ExecutableElement) {\n                    ExecutableElement method = (ExecutableElement) element;\n                    if (checkHasNoErrors(method, messager)) {\n                        TypeElement classElement = (TypeElement) method.getEnclosingElement();\n                        methodsByClass.putElement(classElement, method);\n                    }\n                } else {\n                    messager.printMessage(Diagnostic.Kind.ERROR, \"@Subscribe is only valid for methods\", element);\n                }\n            }\n        }\n    }\n\n    private boolean checkHasNoErrors(ExecutableElement element, Messager messager) {\n        if (element.getModifiers().contains(Modifier.STATIC)) {\n            messager.printMessage(Diagnostic.Kind.ERROR, \"Subscriber method must not be static\", element);\n            return false;\n        }\n\n        if (!element.getModifiers().contains(Modifier.PUBLIC)) {\n            messager.printMessage(Diagnostic.Kind.ERROR, \"Subscriber method must be public\", element);\n            return false;\n        }\n\n        List<? extends VariableElement> parameters = ((ExecutableElement) element).getParameters();\n        if (parameters.size() != 1) {\n            messager.printMessage(Diagnostic.Kind.ERROR, \"Subscriber method must have exactly 1 parameter\", element);\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * Subscriber classes should be skipped if their class or any involved event class are not visible to the index.\n     */\n    private void checkForSubscribersToSkip(Messager messager, String myPackage) {\n        for (TypeElement skipCandidate : methodsByClass.keySet()) {\n            TypeElement subscriberClass = skipCandidate;\n            while (subscriberClass != null) {\n                if (!isVisible(myPackage, subscriberClass)) {\n                    boolean added = classesToSkip.add(skipCandidate);\n                    if (added) {\n                        String msg;\n                        if (subscriberClass.equals(skipCandidate)) {\n                            msg = \"Falling back to reflection because class is not public\";\n                        } else {\n                            msg = \"Falling back to reflection because \" + skipCandidate +\n                                    \" has a non-public super class\";\n                        }\n                        messager.printMessage(Diagnostic.Kind.NOTE, msg, subscriberClass);\n                    }\n                    break;\n                }\n                List<ExecutableElement> methods = methodsByClass.get(subscriberClass);\n                if (methods != null) {\n                    for (ExecutableElement method : methods) {\n                        String skipReason = null;\n                        VariableElement param = method.getParameters().get(0);\n                        TypeMirror typeMirror = getParamTypeMirror(param, messager);\n                        if (!(typeMirror instanceof DeclaredType) ||\n                                !(((DeclaredType) typeMirror).asElement() instanceof TypeElement)) {\n                            skipReason = \"event type cannot be processed\";\n                        }\n                        if (skipReason == null) {\n                            TypeElement eventTypeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();\n                            if (!isVisible(myPackage, eventTypeElement)) {\n                                skipReason = \"event type is not public\";\n                            }\n                        }\n                        if (skipReason != null) {\n                            boolean added = classesToSkip.add(skipCandidate);\n                            if (added) {\n                                String msg = \"Falling back to reflection because \" + skipReason;\n                                if (!subscriberClass.equals(skipCandidate)) {\n                                    msg += \" (found in super class for \" + skipCandidate + \")\";\n                                }\n                                messager.printMessage(Diagnostic.Kind.NOTE, msg, param);\n                            }\n                            break;\n                        }\n                    }\n                }\n                subscriberClass = getSuperclass(subscriberClass);\n            }\n        }\n    }\n\n    private TypeMirror getParamTypeMirror(VariableElement param, Messager messager) {\n        TypeMirror typeMirror = param.asType();\n        // Check for generic type\n        if (typeMirror instanceof TypeVariable) {\n            TypeMirror upperBound = ((TypeVariable) typeMirror).getUpperBound();\n            if (upperBound instanceof DeclaredType) {\n                if (messager != null) {\n                    messager.printMessage(Diagnostic.Kind.NOTE, \"Using upper bound type \" + upperBound +\n                            \" for generic parameter\", param);\n                }\n                typeMirror = upperBound;\n            }\n        }\n        return typeMirror;\n    }\n\n    private TypeElement getSuperclass(TypeElement type) {\n        if (type.getSuperclass().getKind() == TypeKind.DECLARED) {\n            TypeElement superclass = (TypeElement) processingEnv.getTypeUtils().asElement(type.getSuperclass());\n            String name = superclass.getQualifiedName().toString();\n            if (name.startsWith(\"java.\") || name.startsWith(\"javax.\") || name.startsWith(\"android.\")) {\n                // Skip system classes, this just degrades performance\n                return null;\n            } else {\n                return superclass;\n            }\n        } else {\n            return null;\n        }\n    }\n\n    private String getClassString(TypeElement typeElement, String myPackage) {\n        PackageElement packageElement = getPackageElement(typeElement);\n        String packageString = packageElement.getQualifiedName().toString();\n        String className = typeElement.getQualifiedName().toString();\n        if (packageString != null && !packageString.isEmpty()) {\n            if (packageString.equals(myPackage)) {\n                className = cutPackage(myPackage, className);\n            } else if (packageString.equals(\"java.lang\")) {\n                className = typeElement.getSimpleName().toString();\n            }\n        }\n        return className;\n    }\n\n    private String cutPackage(String paket, String className) {\n        if (className.startsWith(paket + '.')) {\n            // Don't use TypeElement.getSimpleName, it doesn't work for us with inner classes\n            return className.substring(paket.length() + 1);\n        } else {\n            // Paranoia\n            throw new IllegalStateException(\"Mismatching \" + paket + \" vs. \" + className);\n        }\n    }\n\n    private PackageElement getPackageElement(TypeElement subscriberClass) {\n        Element candidate = subscriberClass.getEnclosingElement();\n        while (!(candidate instanceof PackageElement)) {\n            candidate = candidate.getEnclosingElement();\n        }\n        return (PackageElement) candidate;\n    }\n\n    private void writeCreateSubscriberMethods(BufferedWriter writer, List<ExecutableElement> methods,\n                                              String callPrefix, String myPackage) throws IOException {\n        for (ExecutableElement method : methods) {\n            List<? extends VariableElement> parameters = method.getParameters();\n            TypeMirror paramType = getParamTypeMirror(parameters.get(0), null);\n            TypeElement paramElement = (TypeElement) processingEnv.getTypeUtils().asElement(paramType);\n            String methodName = method.getSimpleName().toString();\n            String eventClass = getClassString(paramElement, myPackage) + \".class\";\n\n            Subscribe subscribe = method.getAnnotation(Subscribe.class);\n            List<String> parts = new ArrayList<>();\n            parts.add(callPrefix + \"(\\\"\" + methodName + \"\\\",\");\n            String lineEnd = \"),\";\n            if (subscribe.priority() == 0 && !subscribe.sticky()) {\n                if (subscribe.threadMode() == ThreadMode.POSTING) {\n                    parts.add(eventClass + lineEnd);\n                } else {\n                    parts.add(eventClass + \",\");\n                    parts.add(\"ThreadMode.\" + subscribe.threadMode().name() + lineEnd);\n                }\n            } else {\n                parts.add(eventClass + \",\");\n                parts.add(\"ThreadMode.\" + subscribe.threadMode().name() + \",\");\n                parts.add(subscribe.priority() + \",\");\n                parts.add(subscribe.sticky() + lineEnd);\n            }\n            writeLine(writer, 3, parts.toArray(new String[parts.size()]));\n\n            if (verbose) {\n                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, \"Indexed @Subscribe at \" +\n                        method.getEnclosingElement().getSimpleName() + \".\" + methodName +\n                        \"(\" + paramElement.getSimpleName() + \")\");\n            }\n\n        }\n    }\n\n    private void createInfoIndexFile(String index) {\n        BufferedWriter writer = null;\n        try {\n            JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);\n            int period = index.lastIndexOf('.');\n            String myPackage = period > 0 ? index.substring(0, period) : null;\n            String clazz = index.substring(period + 1);\n            writer = new BufferedWriter(sourceFile.openWriter());\n            if (myPackage != null) {\n                writer.write(\"package \" + myPackage + \";\\n\\n\");\n            }\n            writer.write(\"import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\\n\");\n            writer.write(\"import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\\n\");\n            writer.write(\"import org.greenrobot.eventbus.meta.SubscriberInfo;\\n\");\n            writer.write(\"import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\\n\\n\");\n            writer.write(\"import org.greenrobot.eventbus.ThreadMode;\\n\\n\");\n            writer.write(\"import java.util.HashMap;\\n\");\n            writer.write(\"import java.util.Map;\\n\\n\");\n            writer.write(\"/** This class is generated by EventBus, do not edit. */\\n\");\n            writer.write(\"public class \" + clazz + \" implements SubscriberInfoIndex {\\n\");\n            writer.write(\"    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;\\n\\n\");\n            writer.write(\"    static {\\n\");\n            writer.write(\"        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();\\n\\n\");\n            writeIndexLines(writer, myPackage);\n            writer.write(\"    }\\n\\n\");\n            writer.write(\"    private static void putIndex(SubscriberInfo info) {\\n\");\n            writer.write(\"        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\\n\");\n            writer.write(\"    }\\n\\n\");\n            writer.write(\"    @Override\\n\");\n            writer.write(\"    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {\\n\");\n            writer.write(\"        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);\\n\");\n            writer.write(\"        if (info != null) {\\n\");\n            writer.write(\"            return info;\\n\");\n            writer.write(\"        } else {\\n\");\n            writer.write(\"            return null;\\n\");\n            writer.write(\"        }\\n\");\n            writer.write(\"    }\\n\");\n            writer.write(\"}\\n\");\n        } catch (IOException e) {\n            throw new RuntimeException(\"Could not write source for \" + index, e);\n        } finally {\n            if (writer != null) {\n                try {\n                    writer.close();\n                } catch (IOException e) {\n                    //Silent\n                }\n            }\n        }\n    }\n\n    private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {\n        for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {\n            if (classesToSkip.contains(subscriberTypeElement)) {\n                continue;\n            }\n\n            String subscriberClass = getClassString(subscriberTypeElement, myPackage);\n            if (isVisible(myPackage, subscriberTypeElement)) {\n                writeLine(writer, 2,\n                        \"putIndex(new SimpleSubscriberInfo(\" + subscriberClass + \".class,\",\n                        \"true,\", \"new SubscriberMethodInfo[] {\");\n                List<ExecutableElement> methods = methodsByClass.get(subscriberTypeElement);\n                writeCreateSubscriberMethods(writer, methods, \"new SubscriberMethodInfo\", myPackage);\n                writer.write(\"        }));\\n\\n\");\n            } else {\n                writer.write(\"        // Subscriber not visible to index: \" + subscriberClass + \"\\n\");\n            }\n        }\n    }\n\n    private boolean isVisible(String myPackage, TypeElement typeElement) {\n        Set<Modifier> modifiers = typeElement.getModifiers();\n        boolean visible;\n        if (modifiers.contains(Modifier.PUBLIC)) {\n            visible = true;\n        } else if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.PROTECTED)) {\n            visible = false;\n        } else {\n            String subscriberPackage = getPackageElement(typeElement).getQualifiedName().toString();\n            if (myPackage == null) {\n                visible = subscriberPackage.length() == 0;\n            } else {\n                visible = myPackage.equals(subscriberPackage);\n            }\n        }\n        return visible;\n    }\n\n    private void writeLine(BufferedWriter writer, int indentLevel, String... parts) throws IOException {\n        writeLine(writer, indentLevel, 2, parts);\n    }\n\n    private void writeLine(BufferedWriter writer, int indentLevel, int indentLevelIncrease, String... parts)\n            throws IOException {\n        writeIndent(writer, indentLevel);\n        int len = indentLevel * 4;\n        for (int i = 0; i < parts.length; i++) {\n            String part = parts[i];\n            if (i != 0) {\n                if (len + part.length() > 118) {\n                    writer.write(\"\\n\");\n                    if (indentLevel < 12) {\n                        indentLevel += indentLevelIncrease;\n                    }\n                    writeIndent(writer, indentLevel);\n                    len = indentLevel * 4;\n                } else {\n                    writer.write(\" \");\n                }\n            }\n            writer.write(part);\n            len += part.length();\n        }\n        writer.write(\"\\n\");\n    }\n\n    private void writeIndent(BufferedWriter writer, int indentLevel) throws IOException {\n        for (int i = 0; i < indentLevel; i++) {\n            writer.write(\"    \");\n        }\n    }\n}\n"
  },
  {
    "path": "EventBusPerformance/.gitignore",
    "content": "/bin\n/gen\n"
  },
  {
    "path": "EventBusPerformance/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    package=\"org.greenrobot.eventbusperf\">\r\n\r\n    <uses-feature\r\n        android:name=\"android.hardware.touchscreen\"\r\n        android:required=\"false\" />\r\n\r\n    <application\r\n        android:icon=\"@drawable/ic_launcher\"\r\n        android:label=\"@string/app_name\" >\r\n        <activity\r\n            android:name=\"org.greenrobot.eventbusperf.TestSetupActivity\"\r\n            android:label=\"@string/app_name\" >\r\n            <intent-filter>\r\n                <action android:name=\"android.intent.action.MAIN\" />\r\n                <category android:name=\"android.intent.category.LAUNCHER\" />\r\n            </intent-filter>\r\n        </activity>\r\n        <activity\r\n            android:name=\"org.greenrobot.eventbusperf.TestRunnerActivity\"\r\n            android:label=\"@string/app_name\"\r\n            android:process=\"de.greenrobot.eventperf.benchmark\" >\r\n        </activity>\r\n    </application>\r\n\r\n</manifest>"
  },
  {
    "path": "EventBusPerformance/build.gradle",
    "content": "buildscript {\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1\n        classpath 'com.android.tools.build:gradle:4.1.3'\n    }\n}\n\napply plugin: 'com.android.application'\n\ndependencies {\n    implementation project(':eventbus-android')\n    annotationProcessor project(':eventbus-annotation-processor')\n    implementation 'com.squareup:otto:1.3.8'\n}\n\nandroid {\n    compileSdkVersion _compileSdkVersion\n\n    sourceSets {\n        main {\n            manifest.srcFile 'AndroidManifest.xml'\n            java.srcDirs = ['src']\n            res.srcDirs = ['res']\n        }\n    }\n\n    defaultConfig {\n        minSdkVersion 7\n        targetSdkVersion 26\n        versionCode 1\n        versionName \"2.0.0\"\n        javaCompileOptions {\n            annotationProcessorOptions {\n                arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex']\n            }\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\n"
  },
  {
    "path": "EventBusPerformance/proguard-project.txt",
    "content": "# To enable ProGuard in your project, edit project.properties\n# to define the proguard.config property as described in that file.\n#\n# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in ${sdk.dir}/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the ProGuard\n# include property in project.properties.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "EventBusPerformance/project.properties",
    "content": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# This file must be checked in Version Control Systems.\n#\n# To customize properties used by the Ant build system edit\n# \"ant.properties\", and override values to adapt the script to your\n# project structure.\n#\n# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):\n#proguard.config=${sdk.dir}\\tools\\proguard\\proguard-android.txt:proguard-project.txt\n\n# Project target.\ntarget=android-17\n"
  },
  {
    "path": "EventBusPerformance/res/layout/activity_runtests.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:orientation=\"vertical\" >\n\n    <TextView\n        android:id=\"@+id/textViewTestRunning\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:background=\"#88333333\"\n        android:gravity=\"center\"\n        android:padding=\"15dp\"\n        android:text=\"@string/testIsRunning\"\n        android:textColor=\"#ffffff\"\n        android:textSize=\"30sp\"\n        android:textStyle=\"bold\" />\n\n    <ScrollView\n        android:id=\"@+id/scrollViewResults\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        android:layout_above=\"@+id/buttonCancel\"\n        android:fillViewport=\"true\" >\n\n        <TextView\n            android:id=\"@+id/textViewResult\"\n            android:layout_width=\"fill_parent\"\n            android:layout_height=\"wrap_content\"\n            android:textSize=\"16sp\" />\n    </ScrollView>\n\n    <Button\n        android:id=\"@+id/buttonCancel\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_above=\"@+id/buttonKillProcess\"\n        android:layout_alignWithParentIfMissing=\"true\"\n        android:layout_margin=\"16dp\"\n        android:onClick=\"onClickCancel\"\n        android:text=\"@string/buttonCancel\" />\n\n    <Button\n        android:id=\"@+id/buttonKillProcess\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_margin=\"16dp\"\n        android:onClick=\"onClickKillProcess\"\n        android:text=\"@string/buttonKillProcess\"\n        android:visibility=\"gone\" />\n\n</RelativeLayout>"
  },
  {
    "path": "EventBusPerformance/res/layout/activity_setuptests.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/LinearLayout1\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:focusableInTouchMode=\"true\"\n    android:orientation=\"vertical\" >\n\n    <Spinner\n        android:id=\"@+id/spinnerTestToRun\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"14dp\"\n        android:entries=\"@array/spinnerTestsToRun\" />\n\n    <ScrollView\n        android:id=\"@+id/scrollViewSettings\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"0dp\"\n        android:layout_weight=\"1\" >\n\n        <LinearLayout\n            android:id=\"@+id/LinearLayout2\"\n            android:layout_width=\"fill_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:paddingLeft=\"16dp\"\n            android:paddingRight=\"16dp\" >\n\n            <CheckBox\n                android:id=\"@+id/checkBoxEventBus\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:onClick=\"checkEventBus\"\n                android:text=\"@string/test_eventBus\" />\n\n            <Spinner\n                android:id=\"@+id/spinnerThread\"\n                android:layout_width=\"fill_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginLeft=\"48dp\"\n                android:entries=\"@array/spinnerThreadModes\" />\n\n            <CheckBox\n                android:id=\"@+id/checkBoxEventBusEventHierarchy\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:onClick=\"checkEventBus\"\n                android:layout_marginLeft=\"48dp\"\n                android:text=\"@string/test_eventBusEventHierarchy\" />\n\n            <CheckBox\n                android:id=\"@+id/checkBoxEventBusIgnoreGeneratedIndex\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:onClick=\"checkEventBus\"\n                android:layout_marginLeft=\"48dp\"\n                android:text=\"@string/test_eventBusEventIgnoreGeneratedIndex\" />\n\n            <CheckBox\n                android:id=\"@+id/checkBoxOtto\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:layout_marginTop=\"16dp\"\n                android:text=\"@string/test_otto\" />\n\n\n            <CheckBox\n                android:id=\"@+id/checkBoxBroadcast\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/test_broadcast\"\n                android:visibility=\"gone\" />\n\n\n            <CheckBox\n                android:id=\"@+id/checkBoxLocalBroadcast\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginBottom=\"32dp\"\n                android:text=\"@string/test_localBroadcast\"\n                android:visibility=\"gone\" />\n\n            <RelativeLayout\n                android:id=\"@+id/relativeLayoutForEvents\"\n                android:layout_width=\"fill_parent\"\n                android:layout_height=\"fill_parent\"\n                android:layout_marginBottom=\"18dp\" >\n\n                <EditText\n                    android:id=\"@+id/editTextEvent\"\n                    android:layout_width=\"90dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentRight=\"true\"\n                    android:inputType=\"number\"\n                    android:text=\"1000\" />\n\n                <TextView\n                    android:id=\"@+id/eventView\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignBaseline=\"@+id/editTextEvent\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_toLeftOf=\"@+id/editTextEvent\"\n                    android:text=\"@string/eventViewText\" />\n            </RelativeLayout>\n\n            <RelativeLayout\n                android:id=\"@+id/relativeLayoutForSubscribers\"\n                android:layout_width=\"fill_parent\"\n                android:layout_height=\"fill_parent\"\n                android:layout_marginBottom=\"8dp\" >\n\n                <EditText\n                    android:id=\"@+id/editTextSubscribe\"\n                    android:layout_width=\"90dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignParentRight=\"true\"\n                    android:inputType=\"number\"\n                    android:text=\"1\" />\n\n                <TextView\n                    android:id=\"@+id/subscribe\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_alignBaseline=\"@+id/editTextSubscribe\"\n                    android:layout_alignParentLeft=\"true\"\n                    android:layout_toLeftOf=\"@+id/editTextSubscribe\"\n                    android:text=\"@string/subscriberViewText\" />\n            </RelativeLayout>\n        </LinearLayout>\n    </ScrollView>\n\n    <Button\n        android:id=\"@+id/buttonStart\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"50dp\"\n        android:layout_margin=\"16dp\"\n        android:onClick=\"startClick\"\n        android:text=\"@string/buttonStartText\" />\n\n</LinearLayout>"
  },
  {
    "path": "EventBusPerformance/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">EventBus Performance</string>\n    <string name=\"test_eventBus\">EventBus</string>\n    <string name=\"test_eventBusEventHierarchy\">Event Inheritance</string>\n    <string name=\"test_eventBusEventIgnoreGeneratedIndex\">Ignore generated index</string>\n    <string name=\"test_otto\">OttoBus</string>\n    <string name=\"test_broadcast\">Broadcast</string>\n    <string name=\"test_localBroadcast\">Local Broadcast</string>\n    <string name=\"eventViewText\">Events:</string>\n    <string name=\"subscriberViewText\">Subscribers:</string>\n    <string name=\"buttonStartText\">Start</string>\n\n    <string-array name=\"spinnerTestsToRun\">\n        <item>Post Events</item>\n        <item>Register Subscribers</item>\n        <item>Register Subscribers, no unregister</item>\n        <item>Register Subscribers, 1. time</item>\n    </string-array>\n    <string-array name=\"spinnerThreadModes\">\n        <item>POSTING</item>\n        <item>MAIN</item>\n        <item>MAIN_ORDERED</item>\n        <item>BACKGROUND</item>\n        <item>ASYNC</item>\n    </string-array>\n\n    <string name=\"testIsRunning\">Test Is \\nRunning!</string>\n    <string name=\"buttonCancel\">Cancel</string>\n    <string name=\"buttonKillProcess\">Kill Process</string>\n    \n</resources>"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/Test.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf;\n\nimport android.content.Context;\n\nimport java.util.concurrent.atomic.AtomicLong;\n\npublic abstract class Test {\n    protected final Context context;\n    protected final TestParams params;\n    public final AtomicLong eventsReceivedCount = new AtomicLong();\n    protected long primaryResultMicros;\n    protected int primaryResultCount;\n    protected String otherTestResults;\n\n    protected boolean canceled;\n\n    public Test(Context context, TestParams params) {\n        this.context = context;\n        this.params = params;\n    }\n\n    public void cancel() {\n        canceled = true;\n    }\n\n    /** prepares the test, all things which are not relevant for test results */\n    public abstract void prepareTest();\n\n    public abstract void runTest();\n\n    /** returns the display name of the test. e.g. EventBus */\n    public abstract String getDisplayName();\n\n    protected void waitForReceivedEventCount(int expectedEventCount) {\n        while (eventsReceivedCount.get() < expectedEventCount) {\n            try {\n                Thread.sleep(1);\n            } catch (InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n        }\n    }\n\n    public long getPrimaryResultMicros() {\n        return primaryResultMicros;\n    }\n\n    public double getPrimaryResultRate() {\n        return primaryResultCount / (primaryResultMicros / 1000000d);\n    }\n\n    public String getOtherTestResults() {\n        return otherTestResults;\n    }\n\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestEvent.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf;\n\n/** Used by otto and EventBus */\npublic class TestEvent {\n\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestFinishedEvent.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf;\n\npublic class TestFinishedEvent {\n\n    public final Test test;\n    public final boolean isLastEvent;\n\n    public TestFinishedEvent(Test test, boolean isLastEvent) {\n        this.test = test;\n        this.isLastEvent = isLastEvent;\n    }\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestParams.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf;\n\nimport org.greenrobot.eventbus.ThreadMode;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\n\npublic class TestParams implements Serializable {\n    private static final long serialVersionUID = -2739435088947740809L;\n\n    private int eventCount;\n    private int subscriberCount;\n    private int publisherCount;\n    private ThreadMode threadMode;\n    private boolean eventInheritance;\n    private boolean ignoreGeneratedIndex;\n    private int testNumber;\n    private ArrayList<Class<? extends Test>> testClasses;\n\n    public int getEventCount() {\n        return eventCount;\n    }\n\n    public void setEventCount(int iterations) {\n        this.eventCount = iterations;\n    }\n\n    public int getSubscriberCount() {\n        return subscriberCount;\n    }\n\n    public void setSubscriberCount(int subscriberCount) {\n        this.subscriberCount = subscriberCount;\n    }\n\n    public int getPublisherCount() {\n        return publisherCount;\n    }\n\n    public void setPublisherCount(int publisherCount) {\n        this.publisherCount = publisherCount;\n    }\n\n    public ThreadMode getThreadMode() {\n        return threadMode;\n    }\n\n    public void setThreadMode(ThreadMode threadMode) {\n        this.threadMode = threadMode;\n    }\n\n    public boolean isEventInheritance() {\n        return eventInheritance;\n    }\n\n    public void setEventInheritance(boolean eventInheritance) {\n        this.eventInheritance = eventInheritance;\n    }\n\n    public boolean isIgnoreGeneratedIndex() {\n        return ignoreGeneratedIndex;\n    }\n\n    public void setIgnoreGeneratedIndex(boolean ignoreGeneratedIndex) {\n        this.ignoreGeneratedIndex = ignoreGeneratedIndex;\n    }\n\n    public ArrayList<Class<? extends Test>> getTestClasses() {\n        return testClasses;\n    }\n\n    public void setTestClasses(ArrayList<Class<? extends Test>> testClasses) {\n        this.testClasses = testClasses;\n    }\n\n    public int getTestNumber() {\n        return testNumber;\n    }\n\n    public void setTestNumber(int testNumber) {\n        this.testNumber = testNumber;\n    }\n\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunner.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf;\n\nimport android.content.Context;\n\nimport org.greenrobot.eventbus.EventBus;\n\nimport java.lang.reflect.Constructor;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * This thread initialize all selected tests and runs them through. Also the thread skips the tests, when it is canceled\n */\npublic class TestRunner extends Thread {\n    private List<Test> tests;\n    private volatile boolean canceled;\n    private final EventBus controlBus;\n\n    public TestRunner(Context context, TestParams testParams, EventBus controlBus) {\n        this.controlBus = controlBus;\n        tests = new ArrayList<Test>();\n        for (Class<? extends Test> testClazz : testParams.getTestClasses()) {\n            try {\n                Constructor<?>[] constructors = testClazz.getConstructors();\n                Constructor<? extends Test> constructor = testClazz.getConstructor(Context.class, TestParams.class);\n                Test test = constructor.newInstance(context, testParams);\n                tests.add(test);\n            } catch (Exception e) {\n                throw new RuntimeException(e);\n            }\n        }\n    }\n\n    public void run() {\n\n        int idx = 0;\n        for (Test test : tests) {\n            // Clean up and let the main thread calm down\n            System.gc();\n            try {\n                Thread.sleep(300);\n                System.gc();\n                Thread.sleep(300);\n            } catch (InterruptedException e) {\n            }\n\n            test.prepareTest();\n            if (!canceled) {\n                test.runTest();\n            }\n            if (!canceled) {\n                boolean isLastEvent = idx == tests.size() - 1;\n                controlBus.post(new TestFinishedEvent(test, isLastEvent));\n            }\n            idx++;\n        }\n\n    }\n\n    public List<Test> getTests() {\n        return tests;\n    }\n\n    public void cancel() {\n        canceled = true;\n        for (Test test : tests) {\n            test.cancel();\n        }\n    }\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.os.Process;\nimport android.text.Html;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.Subscribe;\nimport org.greenrobot.eventbus.ThreadMode;\n\n/**\n * This activity gets the information from the activity before, sets up the test and starts the test. After it watchs\n * after that, if a test is finished. When a test is finished, the activity appends it on the textview analyse. If all\n * test are finished, it cancels the timer.\n */\npublic class TestRunnerActivity extends Activity {\n\n    private TestRunner testRunner;\n    private EventBus controlBus;\n    private TextView textViewResult;\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_runtests);\n        textViewResult = findViewById(R.id.textViewResult);\n        controlBus = new EventBus();\n        controlBus.register(this);\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        if (testRunner == null) {\n            TestParams testParams = (TestParams) getIntent().getSerializableExtra(\"params\");\n            testRunner = new TestRunner(getApplicationContext(), testParams, controlBus);\n\n            if (testParams.getTestNumber() == 1) {\n                textViewResult.append(\"Events: \" + testParams.getEventCount() + \"\\n\");\n            }\n            textViewResult.append(\"Subscribers: \" + testParams.getSubscriberCount() + \"\\n\\n\");\n            testRunner.start();\n        }\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onEventMainThread(TestFinishedEvent event) {\n        Test test = event.test;\n        String text = \"<b>\" + test.getDisplayName() + \"</b><br/>\" + //\n                test.getPrimaryResultMicros() + \" micro seconds<br/>\" + //\n                ((int) test.getPrimaryResultRate()) + \"/s<br/>\";\n        if (test.getOtherTestResults() != null) {\n            text += test.getOtherTestResults();\n        }\n        text += \"<br/>----------------<br/>\";\n        textViewResult.append(Html.fromHtml(text));\n        if (event.isLastEvent) {\n            findViewById(R.id.buttonCancel).setVisibility(View.GONE);\n            findViewById(R.id.textViewTestRunning).setVisibility(View.GONE);\n            findViewById(R.id.buttonKillProcess).setVisibility(View.VISIBLE);\n        }\n    }\n\n    public void onClickCancel(View view) {\n        // Cancel asap\n        if (testRunner != null) {\n            testRunner.cancel();\n            testRunner = null;\n        }\n        finish();\n    }\n\n    public void onClickKillProcess(View view) {\n        Process.killProcess(Process.myPid());\n    }\n\n    public void onDestroy() {\n        if (testRunner != null) {\n            testRunner.cancel();\n        }\n        controlBus.unregister(this);\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.CheckBox;\nimport android.widget.EditText;\nimport android.widget.Spinner;\n\nimport org.greenrobot.eventbus.ThreadMode;\n\nimport java.util.ArrayList;\n\nimport org.greenrobot.eventbusperf.testsubject.PerfTestEventBus;\nimport org.greenrobot.eventbusperf.testsubject.PerfTestOtto;\n\npublic class TestSetupActivity extends Activity {\n\n    @SuppressWarnings(\"rawtypes\")\n    static final Class[] TEST_CLASSES_EVENTBUS = {PerfTestEventBus.Post.class,//\n            PerfTestEventBus.RegisterOneByOne.class,//\n            PerfTestEventBus.RegisterAll.class, //\n            PerfTestEventBus.RegisterFirstTime.class};\n\n    static final Class[] TEST_CLASSES_OTTO = {PerfTestOtto.Post.class,//\n            PerfTestOtto.RegisterOneByOne.class,//\n            PerfTestOtto.RegisterAll.class, //\n            PerfTestOtto.RegisterFirstTime.class};\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_setuptests);\n\n        Spinner spinnerRun = findViewById(R.id.spinnerTestToRun);\n        spinnerRun.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {\n\n            public void onItemSelected(AdapterView<?> adapter, View v, int pos, long lng) {\n                int eventsVisibility = pos == 0 ? View.VISIBLE : View.GONE;\n                findViewById(R.id.relativeLayoutForEvents).setVisibility(eventsVisibility);\n                findViewById(R.id.spinnerThread).setVisibility(eventsVisibility);\n            }\n\n            public void onNothingSelected(AdapterView<?> arg0) {\n            }\n        });\n    }\n\n    public void checkEventBus(View v) {\n        Spinner spinnerThread = findViewById(R.id.spinnerThread);\n        CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus);\n        int visibility = checkBoxEventBus.isChecked() ? View.VISIBLE : View.GONE;\n        spinnerThread.setVisibility(visibility);\n    }\n\n    public void startClick(View v) {\n        TestParams params = new TestParams();\n        Spinner spinnerThread = findViewById(R.id.spinnerThread);\n        String threadModeStr = spinnerThread.getSelectedItem().toString();\n        ThreadMode threadMode = ThreadMode.valueOf(threadModeStr);\n        params.setThreadMode(threadMode);\n\n        params.setEventInheritance(((CheckBox) findViewById(R.id.checkBoxEventBusEventHierarchy)).isChecked());\n        params.setIgnoreGeneratedIndex(((CheckBox) findViewById(R.id.checkBoxEventBusIgnoreGeneratedIndex)).isChecked());\n\n        EditText editTextEvent = findViewById(R.id.editTextEvent);\n        params.setEventCount(Integer.parseInt(editTextEvent.getText().toString()));\n\n        EditText editTextSubscriber = findViewById(R.id.editTextSubscribe);\n        params.setSubscriberCount(Integer.parseInt(editTextSubscriber.getText().toString()));\n\n        Spinner spinnerTestToRun = findViewById(R.id.spinnerTestToRun);\n        int testPos = spinnerTestToRun.getSelectedItemPosition();\n        params.setTestNumber(testPos + 1);\n        ArrayList<Class<? extends Test>> testClasses = initTestClasses(testPos);\n        params.setTestClasses(testClasses);\n\n        Intent intent = new Intent();\n        intent.setClass(this, TestRunnerActivity.class);\n        intent.putExtra(\"params\", params);\n        startActivity(intent);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private ArrayList<Class<? extends Test>> initTestClasses(int testPos) {\n        ArrayList<Class<? extends Test>> testClasses = new ArrayList<Class<? extends Test>>();\n        // the attributes are putted in the intent (eventbus, otto, broadcast, local broadcast)\n        final CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus);\n        final CheckBox checkBoxOtto = findViewById(R.id.checkBoxOtto);\n        final CheckBox checkBoxBroadcast = findViewById(R.id.checkBoxBroadcast);\n        final CheckBox checkBoxLocalBroadcast = findViewById(R.id.checkBoxLocalBroadcast);\n        if (checkBoxEventBus.isChecked()) {\n            testClasses.add(TEST_CLASSES_EVENTBUS[testPos]);\n        }\n        if (checkBoxOtto.isChecked()) {\n            testClasses.add(TEST_CLASSES_OTTO[testPos]);\n        }\n        if (checkBoxBroadcast.isChecked()) {\n        }\n        if (checkBoxLocalBroadcast.isChecked()) {\n        }\n\n        return testClasses;\n    }\n}"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf.testsubject;\n\nimport android.content.Context;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.Subscribe;\nimport org.greenrobot.eventbus.ThreadMode;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\n\nimport org.greenrobot.eventbusperf.MyEventBusIndex;\nimport org.greenrobot.eventbusperf.Test;\nimport org.greenrobot.eventbusperf.TestEvent;\nimport org.greenrobot.eventbusperf.TestParams;\n\npublic abstract class PerfTestEventBus extends Test {\n\n    private final EventBus eventBus;\n    private final ArrayList<Object> subscribers;\n    private final Class<?> subscriberClass;\n    private final int eventCount;\n    private final int expectedEventCount;\n\n    public PerfTestEventBus(Context context, TestParams params) {\n        super(context, params);\n        eventBus = EventBus.builder().eventInheritance(params.isEventInheritance()).addIndex(new MyEventBusIndex())\n                .ignoreGeneratedIndex(params.isIgnoreGeneratedIndex()).build();\n        subscribers = new ArrayList<Object>();\n        eventCount = params.getEventCount();\n        expectedEventCount = eventCount * params.getSubscriberCount();\n        subscriberClass = getSubscriberClassForThreadMode();\n    }\n\n    @Override\n    public void prepareTest() {\n        try {\n            Constructor<?> constructor = subscriberClass.getConstructor(PerfTestEventBus.class);\n            for (int i = 0; i < params.getSubscriberCount(); i++) {\n                Object subscriber = constructor.newInstance(this);\n                subscribers.add(subscriber);\n            }\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    private Class<?> getSubscriberClassForThreadMode() {\n        switch (params.getThreadMode()) {\n            case MAIN:\n                return SubscribeClassEventBusMain.class;\n            case MAIN_ORDERED:\n                return SubscribeClassEventBusMainOrdered.class;\n            case BACKGROUND:\n                return SubscribeClassEventBusBackground.class;\n            case ASYNC:\n                return SubscriberClassEventBusAsync.class;\n            case POSTING:\n                return SubscribeClassEventBusDefault.class;\n            default:\n                throw new RuntimeException(\"Unknown: \" + params.getThreadMode());\n        }\n    }\n\n    private static String getDisplayModifier(TestParams params) {\n        String inheritance = params.isEventInheritance() ? \"\" : \", no event inheritance\";\n        String ignoreIndex = params.isIgnoreGeneratedIndex() ? \", ignore index\" : \"\";\n        return inheritance + ignoreIndex;\n    }\n\n\n    public static class Post extends PerfTestEventBus {\n        public Post(Context context, TestParams params) {\n            super(context, params);\n        }\n\n        @Override\n        public void prepareTest() {\n            super.prepareTest();\n            super.registerSubscribers();\n        }\n\n        public void runTest() {\n            TestEvent event = new TestEvent();\n            long timeStart = System.nanoTime();\n            for (int i = 0; i < super.eventCount; i++) {\n                super.eventBus.post(event);\n                if (canceled) {\n                    break;\n                }\n            }\n            long timeAfterPosting = System.nanoTime();\n            waitForReceivedEventCount(super.expectedEventCount);\n            long timeAllReceived = System.nanoTime();\n\n            primaryResultMicros = (timeAfterPosting - timeStart) / 1000;\n            primaryResultCount = super.expectedEventCount;\n            long deliveredMicros = (timeAllReceived - timeStart) / 1000;\n            int deliveryRate = (int) (primaryResultCount / (deliveredMicros / 1000000d));\n            otherTestResults = \"Post and delivery time: \" + deliveredMicros + \" micros<br/>\" + //\n                    \"Post and delivery rate: \" + deliveryRate + \"/s\";\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"EventBus Post Events, \" + params.getThreadMode() + getDisplayModifier(params);\n        }\n\n    }\n\n    public static class RegisterAll extends PerfTestEventBus {\n        public RegisterAll(Context context, TestParams params) {\n            super(context, params);\n        }\n\n        public void runTest() {\n            super.registerUnregisterOneSubscribers();\n            long timeNanos = super.registerSubscribers();\n            primaryResultMicros = timeNanos / 1000;\n            primaryResultCount = params.getSubscriberCount();\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"EventBus Register, no unregister\" + getDisplayModifier(params);\n        }\n    }\n\n    public static class RegisterOneByOne extends PerfTestEventBus {\n        protected Method clearCachesMethod;\n\n        public RegisterOneByOne(Context context, TestParams params) {\n            super(context, params);\n        }\n\n        public void runTest() {\n            long time = 0;\n            if (clearCachesMethod == null) {\n                // Skip first registration unless just the first registration is tested\n                super.registerUnregisterOneSubscribers();\n            }\n            for (Object subscriber : super.subscribers) {\n                if (clearCachesMethod != null) {\n                    try {\n                        clearCachesMethod.invoke(null);\n                    } catch (Exception e) {\n                        throw new RuntimeException(e);\n                    }\n                }\n                long beforeRegister = System.nanoTime();\n                super.eventBus.register(subscriber);\n                long afterRegister = System.nanoTime();\n                long end = System.nanoTime();\n                long timeMeasureOverhead = (end - afterRegister) * 2;\n                long timeRegister = end - beforeRegister - timeMeasureOverhead;\n                time += timeRegister;\n                super.eventBus.unregister(subscriber);\n                if (canceled) {\n                    return;\n                }\n            }\n\n            primaryResultMicros = time / 1000;\n            primaryResultCount = params.getSubscriberCount();\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"EventBus Register\" + getDisplayModifier(params);\n        }\n    }\n\n    public static class RegisterFirstTime extends RegisterOneByOne {\n\n        public RegisterFirstTime(Context context, TestParams params) {\n            super(context, params);\n            try {\n                Class<?> clazz = Class.forName(\"org.greenrobot.eventbus.SubscriberMethodFinder\");\n                clearCachesMethod = clazz.getDeclaredMethod(\"clearCaches\");\n                clearCachesMethod.setAccessible(true);\n            } catch (Exception e) {\n                throw new RuntimeException(e);\n            }\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"EventBus Register, first time\"+ getDisplayModifier(params);\n        }\n\n    }\n\n    public class SubscribeClassEventBusMain {\n        @Subscribe(threadMode = ThreadMode.MAIN)\n        public void onEventMainThread(TestEvent event) {\n            eventsReceivedCount.incrementAndGet();\n        }\n\n        public void dummy() {\n        }\n\n        public void dummy2() {\n        }\n\n        public void dummy3() {\n        }\n\n        public void dummy4() {\n        }\n\n        public void dummy5() {\n        }\n    }\n\n    public class SubscribeClassEventBusMainOrdered {\n        @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)\n        public void onEvent(TestEvent event) {\n            eventsReceivedCount.incrementAndGet();\n        }\n\n        public void dummy() {\n        }\n\n        public void dummy2() {\n        }\n\n        public void dummy3() {\n        }\n\n        public void dummy4() {\n        }\n\n        public void dummy5() {\n        }\n    }\n\n    public class SubscribeClassEventBusBackground {\n        @Subscribe(threadMode = ThreadMode.BACKGROUND)\n        public void onEventBackgroundThread(TestEvent event) {\n            eventsReceivedCount.incrementAndGet();\n        }\n\n        public void dummy() {\n        }\n\n        public void dummy2() {\n        }\n\n        public void dummy3() {\n        }\n\n        public void dummy4() {\n        }\n\n        public void dummy5() {\n        }\n    }\n\n    public class SubscriberClassEventBusAsync {\n        @Subscribe(threadMode = ThreadMode.ASYNC)\n        public void onEventAsync(TestEvent event) {\n            eventsReceivedCount.incrementAndGet();\n        }\n\n        public void dummy() {\n        }\n\n        public void dummy2() {\n        }\n\n        public void dummy3() {\n        }\n\n        public void dummy4() {\n        }\n\n        public void dummy5() {\n        }\n    }\n\n    private long registerSubscribers() {\n        long time = 0;\n        for (Object subscriber : subscribers) {\n            long timeStart = System.nanoTime();\n            eventBus.register(subscriber);\n            long timeEnd = System.nanoTime();\n            time += timeEnd - timeStart;\n            if (canceled) {\n                return 0;\n            }\n        }\n        return time;\n    }\n\n    private void registerUnregisterOneSubscribers() {\n        if (!subscribers.isEmpty()) {\n            Object subscriber = subscribers.get(0);\n            eventBus.register(subscriber);\n            eventBus.unregister(subscriber);\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestOtto.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf.testsubject;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.os.Looper;\n\nimport com.squareup.otto.Bus;\nimport com.squareup.otto.Subscribe;\nimport com.squareup.otto.ThreadEnforcer;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.greenrobot.eventbusperf.Test;\nimport org.greenrobot.eventbusperf.TestEvent;\nimport org.greenrobot.eventbusperf.TestParams;\n\npublic abstract class PerfTestOtto extends Test {\n\n    private final Bus eventBus;\n    private final ArrayList<Object> subscribers;\n    private final Class<?> subscriberClass;\n    private final int eventCount;\n    private final int expectedEventCount;\n\n    public PerfTestOtto(Context context, TestParams params) {\n        super(context, params);\n        eventBus = new Bus(ThreadEnforcer.ANY);\n        subscribers = new ArrayList<Object>();\n        eventCount = params.getEventCount();\n        expectedEventCount = eventCount * params.getSubscriberCount();\n        subscriberClass = Subscriber.class;\n    }\n\n    @Override\n    public void prepareTest() {\n        Looper.prepare();\n\n        try {\n            Constructor<?> constructor = subscriberClass.getConstructor(PerfTestOtto.class);\n            for (int i = 0; i < params.getSubscriberCount(); i++) {\n                Object subscriber = constructor.newInstance(this);\n                subscribers.add(subscriber);\n            }\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public static class Post extends PerfTestOtto {\n        public Post(Context context, TestParams params) {\n            super(context, params);\n        }\n\n        @Override\n        public void prepareTest() {\n            super.prepareTest();\n            super.registerSubscribers();\n        }\n\n        public void runTest() {\n            TestEvent event = new TestEvent();\n            long timeStart = System.nanoTime();\n            for (int i = 0; i < super.eventCount; i++) {\n                super.eventBus.post(event);\n                if (canceled) {\n                    break;\n                }\n            }\n            long timeAfterPosting = System.nanoTime();\n            waitForReceivedEventCount(super.expectedEventCount);\n\n            primaryResultMicros = (timeAfterPosting - timeStart) / 1000;\n            primaryResultCount = super.expectedEventCount;\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"Otto Post Events\";\n        }\n    }\n\n    public static class RegisterAll extends PerfTestOtto {\n        public RegisterAll(Context context, TestParams params) {\n            super(context, params);\n        }\n\n        public void runTest() {\n            super.registerUnregisterOneSubscribers();\n            long timeNanos = super.registerSubscribers();\n            primaryResultMicros = timeNanos / 1000;\n            primaryResultCount = params.getSubscriberCount();\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"Otto Register, no unregister\";\n        }\n    }\n\n    public static class RegisterOneByOne extends PerfTestOtto {\n        protected Field cacheField;\n\n        public RegisterOneByOne(Context context, TestParams params) {\n            super(context, params);\n        }\n\n        @SuppressWarnings(\"rawtypes\")\n        public void runTest() {\n            long time = 0;\n            if (cacheField == null) {\n                // Skip first registration unless just the first registration is tested\n                super.registerUnregisterOneSubscribers();\n            }\n            for (Object subscriber : super.subscribers) {\n                if (cacheField != null) {\n                    try {\n                        cacheField.set(null, new ConcurrentHashMap());\n                    } catch (Exception e) {\n                        throw new RuntimeException(e);\n                    }\n                }\n                long beforeRegister = System.nanoTime();\n                super.eventBus.register(subscriber);\n\n                long afterRegister = System.nanoTime();\n                long end = System.nanoTime();\n                long timeMeasureOverhead = (end - afterRegister) * 2;\n                long timeRegister = end - beforeRegister - timeMeasureOverhead;\n                time += timeRegister;\n                super.eventBus.unregister(subscriber);\n                if (canceled) {\n                    return;\n                }\n            }\n\n            primaryResultMicros = time / 1000;\n            primaryResultCount = params.getSubscriberCount();\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"Otto Register\";\n        }\n    }\n\n    public static class RegisterFirstTime extends RegisterOneByOne {\n\n        public RegisterFirstTime(Context context, TestParams params) {\n            super(context, params);\n            try {\n                Class<?> clazz = Class.forName(\"com.squareup.otto.AnnotatedHandlerFinder\");\n                cacheField = clazz.getDeclaredField(\"SUBSCRIBERS_CACHE\");\n                cacheField.setAccessible(true);\n            } catch (Exception e) {\n                throw new RuntimeException(e);\n            }\n        }\n\n        @Override\n        public String getDisplayName() {\n            return \"Otto Register, first time\";\n        }\n\n    }\n\n    public class Subscriber extends Activity {\n        public Subscriber() {\n        }\n\n        @Subscribe\n        public void onEvent(TestEvent event) {\n            eventsReceivedCount.incrementAndGet();\n        }\n\n        public void dummy() {\n        }\n\n        public void dummy2() {\n        }\n\n        public void dummy3() {\n        }\n\n        public void dummy4() {\n        }\n\n        public void dummy5() {\n        }\n\n    }\n\n    private long registerSubscribers() {\n        long time = 0;\n        for (Object subscriber : subscribers) {\n            long timeStart = System.nanoTime();\n            eventBus.register(subscriber);\n            long timeEnd = System.nanoTime();\n            time += timeEnd - timeStart;\n            if (canceled) {\n                return 0;\n            }\n        }\n        return time;\n    }\n\n    private void registerUnregisterOneSubscribers() {\n        if (!subscribers.isEmpty()) {\n            Object subscriber = subscribers.get(0);\n            eventBus.register(subscriber);\n            eventBus.unregister(subscriber);\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/SubscribeClassEventBusDefault.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbusperf.testsubject;\n\nimport org.greenrobot.eventbus.Subscribe;\n\nimport org.greenrobot.eventbusperf.TestEvent;\n\npublic class SubscribeClassEventBusDefault {\n    private PerfTestEventBus perfTestEventBus;\n\n    public SubscribeClassEventBusDefault(PerfTestEventBus perfTestEventBus) {\n        this.perfTestEventBus = perfTestEventBus;\n    }\n\n    @Subscribe\n    public void onEvent(TestEvent event) {\n        perfTestEventBus.eventsReceivedCount.incrementAndGet();\n    }\n\n    public void dummy() {\n    }\n\n    public void dummy2() {\n    }\n\n    public void dummy3() {\n    }\n\n    public void dummy4() {\n    }\n\n    public void dummy5() {\n    }\n}\n"
  },
  {
    "path": "EventBusTest/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:tools=\"http://schemas.android.com/tools\"\r\n    package=\"org.greenrobot.eventbus\">\r\n\r\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>\r\n\r\n    <application\r\n        android:allowBackup=\"false\"\r\n        android:label=\"EventBus Test\"\r\n        tools:ignore=\"GoogleAppIndexingWarning,MissingApplicationIcon\">\r\n    </application>\r\n\r\n</manifest>"
  },
  {
    "path": "EventBusTest/build.gradle",
    "content": "buildscript {\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1\n        classpath 'com.android.tools.build:gradle:4.1.3'\n    }\n}\n\napply plugin: 'com.android.application'\n\ndependencies {\n    androidTestImplementation project(':eventbus-android')\n    androidTestImplementation project(':EventBusTestJava')\n    androidTestAnnotationProcessor project(':eventbus-annotation-processor')\n    // Trying to repro bug:\n//    androidTestAnnotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.0'\n    implementation fileTree(dir: 'libs', include: '*.jar')\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    androidTestImplementation 'com.android.support.test:rules:1.0.2'\n}\n\nandroid {\n    compileSdkVersion _compileSdkVersion\n\n    compileOptions {\n        sourceCompatibility = JavaVersion.VERSION_1_7\n        targetCompatibility = JavaVersion.VERSION_1_7\n    }\n\n    sourceSets {\n        main {\n            manifest.srcFile 'AndroidManifest.xml'\n        }\n\n        androidTest {\n            java.srcDirs = ['src']\n        }\n    }\n\n    defaultConfig {\n        minSdkVersion 9\n        targetSdkVersion 26\n        versionCode 1\n        versionName \"1.0\"\n\n        testApplicationId \"de.greenrobot.event.test\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n\n        javaCompileOptions {\n            annotationProcessorOptions {\n                arguments = [ eventBusIndex : 'org.greenrobot.eventbus.EventBusTestsIndex' ]\n            }\n        }\n    }\n\n    useLibrary 'android.test.base'\n\n    lintOptions {\n        // To see problems right away, also nice for Travis CI\n        textOutput 'stdout'\n\n        // TODO FIXME: Travis only error\n        abortOnError false\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport android.annotation.SuppressLint;\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.os.Message;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Before;\nimport org.junit.runner.RunWith;\n\n\nimport static org.junit.Assert.assertFalse;\n\n/**\n * @author Markus Junginger, greenrobot\n */\n@RunWith(AndroidJUnit4.class)\npublic abstract class AbstractAndroidEventBusTest extends AbstractEventBusTest {\n    private EventPostHandler mainPoster;\n\n    public AbstractAndroidEventBusTest() {\n        this(false);\n    }\n\n    public AbstractAndroidEventBusTest(boolean collectEventsReceived) {\n        super(collectEventsReceived);\n    }\n\n    @Before\n    public void setUpAndroid() throws Exception {\n        mainPoster = new EventPostHandler(Looper.getMainLooper());\n        assertFalse(Looper.getMainLooper().getThread().equals(Thread.currentThread()));\n    }\n\n    protected void postInMainThread(Object event) {\n        mainPoster.post(event);\n    }\n\n    @SuppressLint(\"HandlerLeak\")\n    class EventPostHandler extends Handler {\n        public EventPostHandler(Looper looper) {\n            super(looper);\n        }\n\n        @Override\n        public void handleMessage(Message msg) {\n            eventBus.post(msg.obj);\n        }\n\n        void post(Object event) {\n            sendMessage(obtainMessage(0, event));\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java",
    "content": "package org.greenrobot.eventbus;\n\nimport org.greenrobot.eventbus.android.AndroidComponents;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\npublic class AndroidComponentsAvailabilityTest {\n\n    @Test\n    public void shouldBeAvailable() {\n        assertTrue(AndroidComponents.areAvailable());\n        assertNotNull(AndroidComponents.get());\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/ClassMapPerfTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus;\n\nimport java.util.HashMap;\nimport java.util.IdentityHashMap;\nimport java.util.Map;\n\n/**\n * Just to verify testHashMapClassObject is fastest. Ignore this test.\n */\npublic class ClassMapPerfTest /* extends TestCase */ {\n\n    static final int COUNT = 10000000;\n    static final Class CLAZZ = ClassMapPerfTest.class;\n\n    public void testHashMapClassObject() {\n        Map<Class, Class> map = new HashMap<Class, Class>();\n        for (int i = 0; i < COUNT; i++) {\n            Class oldValue = map.put(CLAZZ, CLAZZ);\n            Class value = map.get(CLAZZ);\n        }\n    }\n\n    public void testIdentityHashMapClassObject() {\n        Map<Class, Class> map = new IdentityHashMap<Class, Class>();\n        for (int i = 0; i < COUNT; i++) {\n            Class oldValue = map.put(CLAZZ, CLAZZ);\n            Class value = map.get(CLAZZ);\n        }\n    }\n\n    public void testHashMapClassName() {\n        Map<String, Class> map = new HashMap<String, Class>();\n        for (int i = 0; i < COUNT; i++) {\n            Class oldValue = map.put(CLAZZ.getName(), CLAZZ);\n            Class value = map.get(CLAZZ.getName());\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport android.app.Activity;\nimport android.support.test.annotation.UiThreadTest;\nimport android.support.test.rule.UiThreadTestRule;\nimport android.util.Log;\n\nimport org.junit.Rule;\nimport org.junit.Test;\n\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author Markus Junginger, greenrobot\n */\n// Do not extend from AbstractAndroidEventBusTest, because it asserts test may not be in main thread\npublic class EventBusAndroidActivityTest extends AbstractEventBusTest {\n\n    public static class WithIndex extends EventBusBasicTest {\n        @Test\n        public void dummy() {\n        }\n\n    }\n\n    @Rule\n    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();\n\n    @Test\n    @UiThreadTest\n    public void testRegisterAndPost() {\n        // Use an activity to test real life performance\n        TestActivity testActivity = new TestActivity();\n        String event = \"Hello\";\n\n        long start = System.currentTimeMillis();\n        eventBus.register(testActivity);\n        long time = System.currentTimeMillis() - start;\n        Log.d(EventBus.TAG, \"Registered in \" + time + \"ms\");\n\n        eventBus.post(event);\n\n        assertEquals(event, testActivity.lastStringEvent);\n    }\n\n    public static class TestActivity extends Activity {\n        public String lastStringEvent;\n\n        @Subscribe\n        public void onEvent(String event) {\n            lastStringEvent = event;\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport android.support.test.runner.AndroidJUnit4;\nimport android.test.UiThreadTest;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\n\n@RunWith(AndroidJUnit4.class)\npublic class EventBusAndroidCancelEventDeliveryTest extends EventBusCancelEventDeliveryTest {\n\n    @UiThreadTest\n    @Test\n    public void testCancelInMainThread() {\n        SubscriberMainThread subscriber = new SubscriberMainThread();\n        eventBus.register(subscriber);\n        eventBus.post(\"42\");\n        awaitLatch(subscriber.done, 10);\n        assertEquals(0, eventCount.intValue());\n        assertNotNull(failed);\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport android.os.Looper;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertSame;\n\n@RunWith(AndroidJUnit4.class)\npublic class EventBusAndroidMultithreadedTest extends EventBusMultithreadedTest {\n\n    @Test\n    public void testSubscribeUnSubscribeAndPostMixedEventType() throws InterruptedException {\n        List<SubscribeUnsubscribeThread> threads = new ArrayList<SubscribeUnsubscribeThread>();\n\n        // Debug.startMethodTracing(\"testSubscribeUnSubscribeAndPostMixedEventType\");\n        for (int i = 0; i < 5; i++) {\n            SubscribeUnsubscribeThread thread = new SubscribeUnsubscribeThread();\n            thread.start();\n            threads.add(thread);\n        }\n        // This test takes a bit longer, so just use fraction the regular count\n        runThreadsMixedEventType(COUNT / 4, 5);\n        for (SubscribeUnsubscribeThread thread : threads) {\n            thread.shutdown();\n        }\n        for (SubscribeUnsubscribeThread thread : threads) {\n            thread.join();\n        }\n        // Debug.stopMethodTracing();\n    }\n\n    public class SubscribeUnsubscribeThread extends Thread {\n        boolean running = true;\n\n        public void shutdown() {\n            running = false;\n        }\n\n        @Override\n        public void run() {\n            try {\n                while (running) {\n                    eventBus.register(this);\n                    double random = Math.random();\n                    if (random > 0.6d) {\n                        Thread.sleep(0, (int) (1000000 * Math.random()));\n                    } else if (random > 0.3d) {\n                        Thread.yield();\n                    }\n                    eventBus.unregister(this);\n                }\n            } catch (InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n        }\n\n        @Subscribe(threadMode = ThreadMode.MAIN)\n        public void onEventMainThread(String event) {\n            assertSame(Looper.getMainLooper(), Looper.myLooper());\n        }\n\n        @Subscribe(threadMode = ThreadMode.BACKGROUND)\n        public void onEventBackgroundThread(Integer event) {\n            assertNotSame(Looper.getMainLooper(), Looper.myLooper());\n        }\n\n        @Subscribe\n        public void onEvent(Object event) {\n            assertNotSame(Looper.getMainLooper(), Looper.myLooper());\n        }\n\n        @Subscribe(threadMode = ThreadMode.ASYNC)\n        public void onEventAsync(Object event) {\n            assertNotSame(Looper.getMainLooper(), Looper.myLooper());\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java",
    "content": "package org.greenrobot.eventbus;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\n\nimport static org.junit.Assert.assertEquals;\n\npublic class EventBusAndroidOrderTest extends AbstractAndroidEventBusTest {\n\n    private TestBackgroundPoster backgroundPoster;\n    private Handler handler;\n\n    @Before\n    public void setUp() throws Exception {\n        handler = new Handler(Looper.getMainLooper());\n        backgroundPoster = new TestBackgroundPoster(eventBus);\n        backgroundPoster.start();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        backgroundPoster.shutdown();\n        backgroundPoster.join();\n    }\n\n    @Test\n    public void backgroundAndMainUnordered() {\n        eventBus.register(this);\n\n        handler.post(new Runnable() {\n            @Override\n            public void run() {\n                // post from non-main thread\n                backgroundPoster.post(\"non-main\");\n                // post from main thread\n                eventBus.post(\"main\");\n            }\n        });\n\n        waitForEventCount(2, 1000);\n\n        // observe that event from *main* thread is posted FIRST\n        // NOT in posting order\n        assertEquals(\"non-main\", lastEvent);\n    }\n\n    @Test\n    public void backgroundAndMainOrdered() {\n        eventBus.register(this);\n\n        handler.post(new Runnable() {\n            @Override\n            public void run() {\n                // post from non-main thread\n                backgroundPoster.post(new OrderedEvent(\"non-main\"));\n                // post from main thread\n                eventBus.post(new OrderedEvent(\"main\"));\n            }\n        });\n\n        waitForEventCount(2, 1000);\n\n        // observe that event from *main* thread is posted LAST\n        // IN posting order\n        assertEquals(\"main\", ((OrderedEvent) lastEvent).thread);\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onEvent(String event) {\n        trackEvent(event);\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)\n    public void onEvent(OrderedEvent event) {\n        trackEvent(event);\n    }\n\n    static class OrderedEvent {\n        String thread;\n\n        OrderedEvent(String thread) {\n            this.thread = thread;\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport android.os.Looper;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusBackgroundThreadTest extends AbstractAndroidEventBusTest {\n\n    @Test\n    public void testPostInCurrentThread() throws InterruptedException {\n        eventBus.register(this);\n        eventBus.post(\"Hello\");\n        waitForEventCount(1, 1000);\n\n        assertEquals(\"Hello\", lastEvent);\n        assertEquals(Thread.currentThread(), lastThread);\n    }\n\n    @Test\n    public void testPostFromMain() throws InterruptedException {\n        eventBus.register(this);\n        postInMainThread(\"Hello\");\n        waitForEventCount(1, 1000);\n        assertEquals(\"Hello\", lastEvent);\n        assertFalse(lastThread.equals(Thread.currentThread()));\n        assertFalse(lastThread.equals(Looper.getMainLooper().getThread()));\n    }\n\n    @Subscribe(threadMode = ThreadMode.BACKGROUND)\n    public void onEventBackgroundThread(String event) {\n        trackEvent(event);\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport org.junit.Test;\n\nimport java.util.Random;\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusMainThreadRacingTest extends AbstractAndroidEventBusTest {\n\n    private static final int ITERATIONS = LONG_TESTS ? 100000 : 1000;\n\n    protected boolean unregistered;\n    private CountDownLatch startLatch;\n    private volatile RuntimeException failed;\n\n    @Test\n    public void testRacingThreads() throws InterruptedException {\n        Runnable register = new Runnable() {\n            @Override\n            public void run() {\n                eventBus.register(EventBusMainThreadRacingTest.this);\n                unregistered = false;\n            }\n        };\n\n        Runnable unregister = new Runnable() {\n            @Override\n            public void run() {\n                eventBus.unregister(EventBusMainThreadRacingTest.this);\n                unregistered = true;\n            }\n        };\n\n        startLatch = new CountDownLatch(2);\n        BackgroundPoster backgroundPoster = new BackgroundPoster();\n        backgroundPoster.start();\n        try {\n            Handler handler = new Handler(Looper.getMainLooper());\n            Random random = new Random();\n            countDownAndAwaitLatch(startLatch, 10);\n            for (int i = 0; i < ITERATIONS; i++) {\n                handler.post(register);\n                Thread.sleep(0, random.nextInt(300)); // Sleep just some nanoseconds, timing is crucial here\n                handler.post(unregister);\n                if (failed != null) {\n                    throw new RuntimeException(\"Failed in iteration \" + i, failed);\n                }\n                // Don't let the queue grow to avoid out-of-memory scenarios\n                waitForHandler(handler);\n            }\n        } finally {\n            backgroundPoster.running = false;\n            backgroundPoster.join();\n        }\n    }\n\n    protected void waitForHandler(Handler handler) {\n        final CountDownLatch doneLatch = new CountDownLatch(1);\n        handler.post(new Runnable() {\n\n            @Override\n            public void run() {\n                doneLatch.countDown();\n            }\n        });\n        awaitLatch(doneLatch, 10);\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onEventMainThread(String event) {\n        trackEvent(event);\n        if (unregistered) {\n            failed = new RuntimeException(\"Main thread event delivered while unregistered on received event #\"\n                    + eventCount);\n        }\n    }\n\n    class BackgroundPoster extends Thread {\n        volatile boolean running = true;\n\n        public BackgroundPoster() {\n            super(\"BackgroundPoster\");\n        }\n\n        @Override\n        public void run() {\n            countDownAndAwaitLatch(startLatch, 10);\n            while (running) {\n                eventBus.post(\"Posted in background\");\n                if (Math.random() > 0.9f) {\n                    // Single cores would take very long without yielding\n                    Thread.yield();\n                }\n            }\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport android.os.Looper;\n\nimport org.junit.Test;\n\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusMainThreadTest extends AbstractAndroidEventBusTest {\n\n    @Test\n    public void testPost() throws InterruptedException {\n        eventBus.register(this);\n        eventBus.post(\"Hello\");\n        waitForEventCount(1, 1000);\n\n        assertEquals(\"Hello\", lastEvent);\n        assertEquals(Looper.getMainLooper().getThread(), lastThread);\n    }\n\n    @Test\n    public void testPostInBackgroundThread() throws InterruptedException {\n        TestBackgroundPoster backgroundPoster = new TestBackgroundPoster(eventBus);\n        backgroundPoster.start();\n\n        eventBus.register(this);\n        backgroundPoster.post(\"Hello\");\n        waitForEventCount(1, 1000);\n        assertEquals(\"Hello\", lastEvent);\n        assertEquals(Looper.getMainLooper().getThread(), lastThread);\n\n        backgroundPoster.shutdown();\n        backgroundPoster.join();\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onEventMainThread(String event) {\n        trackEvent(event);\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport android.os.Looper;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertSame;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusMethodModifiersTest extends AbstractAndroidEventBusTest {\n\n    @Test\n    public void testRegisterForEventTypeAndPost() throws InterruptedException {\n        eventBus.register(this);\n        String event = \"Hello\";\n        eventBus.post(event);\n        waitForEventCount(4, 1000);\n    }\n\n    @Subscribe\n    public void onEvent(String event) {\n        trackEvent(event);\n        assertNotSame(Looper.getMainLooper(), Looper.myLooper());\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onEventMainThread(String event) {\n        trackEvent(event);\n        assertSame(Looper.getMainLooper(), Looper.myLooper());\n    }\n\n    @Subscribe(threadMode = ThreadMode.BACKGROUND)\n    public void onEventBackgroundThread(String event) {\n        trackEvent(event);\n        assertNotSame(Looper.getMainLooper(), Looper.myLooper());\n    }\n\n    @Subscribe(threadMode = ThreadMode.ASYNC)\n    public void onEventAsync(String event) {\n        trackEvent(event);\n        assertNotSame(Looper.getMainLooper(), Looper.myLooper());\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java",
    "content": "package org.greenrobot.eventbus;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class TestBackgroundPoster extends Thread {\n    private final EventBus eventBus;\n    volatile boolean running = true;\n    private final List<Object> eventQ = new ArrayList<>();\n    private final List<Object> eventsDone = new ArrayList<>();\n\n    TestBackgroundPoster(EventBus eventBus) {\n        super(\"BackgroundPoster\");\n        this.eventBus = eventBus;\n    }\n\n    @Override\n    public void run() {\n        while (running) {\n            Object event = pollEvent();\n            if (event != null) {\n                eventBus.post(event);\n                synchronized (eventsDone) {\n                    eventsDone.add(event);\n                    eventsDone.notifyAll();\n                }\n            }\n        }\n    }\n\n    private synchronized Object pollEvent() {\n        Object event = null;\n        synchronized (eventQ) {\n            if (eventQ.isEmpty()) {\n                try {\n                    eventQ.wait(1000);\n                } catch (InterruptedException ignored) {\n                }\n            }\n            if(!eventQ.isEmpty()) {\n                event = eventQ.remove(0);\n            }\n        }\n        return event;\n    }\n\n    void shutdown() {\n        running = false;\n        synchronized (eventQ) {\n            eventQ.notifyAll();\n        }\n    }\n\n    void post(Object event) {\n        synchronized (eventQ) {\n            eventQ.add(event);\n            eventQ.notifyAll();\n        }\n        synchronized (eventsDone) {\n            while (!eventsDone.remove(event)) {\n                try {\n                    eventsDone.wait();\n                } catch (InterruptedException e) {\n                    throw new RuntimeException(e);\n                }\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java",
    "content": "package org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusAndroidOrderTest;\n\npublic class EventBusAndroidOrderTestWithIndex extends EventBusAndroidOrderTest {\n\n    @Override\n    public void setUp() throws Exception {\n        eventBus = Indexed.build();\n        super.setUp();\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusBackgroundThreadTest;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertTrue;\n\npublic class EventBusBackgroundThreadTestWithIndex extends EventBusBackgroundThreadTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n\n    @Test\n    public void testIndex() {\n        assertTrue(eventBus.toString().contains(\"indexCount=2\"));\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusBasicTest;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertTrue;\n\npublic class EventBusBasicTestWithIndex extends EventBusBasicTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n\n    @Test\n    public void testIndex() {\n        assertTrue(eventBus.toString().contains(\"indexCount=2\"));\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusCancelEventDeliveryTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusCancelEventDeliveryTest;\nimport org.junit.Before;\n\npublic class EventBusCancelEventDeliveryTestWithIndex extends EventBusCancelEventDeliveryTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusFallbackToReflectionTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.junit.Before;\n\nimport org.greenrobot.eventbus.EventBusFallbackToReflectionTest;\n\npublic class EventBusFallbackToReflectionTestWithIndex extends EventBusFallbackToReflectionTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusGenericsTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.junit.Before;\n\nimport org.greenrobot.eventbus.EventBusGenericsTest;\n\npublic class EventBusGenericsTestWithIndex extends EventBusGenericsTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceDisabledTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.EventBusTestsIndex;\nimport org.junit.Before;\n\nimport org.greenrobot.eventbus.EventBusInheritanceDisabledTest;\n\npublic class EventBusInheritanceDisabledTestWithIndex extends EventBusInheritanceDisabledTest {\n    @Before\n    public void setUp() throws Exception {\n        eventBus = EventBus.builder().eventInheritance(false).addIndex(new EventBusTestsIndex()).build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusInheritanceTest;\nimport org.junit.Before;\n\npublic class EventBusInheritanceTestWithIndex extends EventBusInheritanceTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadRacingTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.junit.Before;\n\nimport org.greenrobot.eventbus.EventBusMainThreadRacingTest;\n\npublic class EventBusMainThreadRacingTestWithIndex extends EventBusMainThreadRacingTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.junit.Before;\n\nimport org.greenrobot.eventbus.EventBusMainThreadTest;\n\npublic class EventBusMainThreadTestWithIndex extends EventBusMainThreadTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMethodModifiersTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusMethodModifiersTest;\nimport org.junit.Before;\n\npublic class EventBusMethodModifiersTestWithIndex extends EventBusMethodModifiersTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMultithreadedTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusMultithreadedTest;\nimport org.junit.Before;\n\npublic class EventBusMultithreadedTestWithIndex extends EventBusMultithreadedTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusNoSubscriberEventTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusNoSubscriberEventTest;\nimport org.junit.Before;\n\npublic class EventBusNoSubscriberEventTestWithIndex extends EventBusNoSubscriberEventTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusOrderedSubscriptionsTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusOrderedSubscriptionsTest;\nimport org.junit.Before;\n\npublic class EventBusOrderedSubscriptionsTestWithIndex extends EventBusOrderedSubscriptionsTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusRegistrationRacingTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.junit.Before;\n\nimport org.greenrobot.eventbus.EventBusRegistrationRacingTest;\n\npublic class EventBusRegistrationRacingTestWithIndex extends EventBusRegistrationRacingTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusStickyEventTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusStickyEventTest;\nimport org.junit.Before;\n\npublic class EventBusStickyEventTestWithIndex extends EventBusStickyEventTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberExceptionTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.junit.Before;\n\nimport org.greenrobot.eventbus.EventBusSubscriberExceptionTest;\n\npublic class EventBusSubscriberExceptionTestWithIndex extends EventBusSubscriberExceptionTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = Indexed.build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberInJarTestWithIndex.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.EventBusSubscriberInJarTest;\nimport org.greenrobot.eventbus.InJarIndex;\nimport org.junit.Before;\n\npublic class EventBusSubscriberInJarTestWithIndex extends EventBusSubscriberInJarTest {\n    @Before\n    public void overwriteEventBus() throws Exception {\n        eventBus = EventBus.builder().addIndex(new InJarIndex()).build();\n    }\n}\n"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.EventBusJavaTestsIndex;\nimport org.greenrobot.eventbus.EventBusTestsIndex;\n\npublic class Indexed {\n    static EventBus build() {\n        return EventBus.builder()\n                .addIndex(new EventBusTestsIndex())\n                .addIndex(new EventBusJavaTestsIndex())\n                .build();\n    }\n}\n"
  },
  {
    "path": "EventBusTestJava/build.gradle",
    "content": "apply plugin: \"java-library\"\n\njava.sourceCompatibility = JavaVersion.VERSION_1_8\njava.targetCompatibility = JavaVersion.VERSION_1_8\n\n// we have tests in the main source set so they can be shared with the Android test module\n// to make Gradle pick them up, add the dir to the test source set\nsourceSets {\n    test {\n        java {\n            srcDirs += [\"src/main/java\"]\n        }\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: \"libs\", include: \"*.jar\")\n    implementation(project(\":eventbus-java\"))\n    annotationProcessor project(\":eventbus-annotation-processor\")\n    implementation \"junit:junit:4.13.2\"\n}\n\ntasks.withType(JavaCompile) {\n    options.compilerArgs += [ \"-AeventBusIndex=org.greenrobot.eventbus.EventBusJavaTestsIndex\" ]\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java",
    "content": "/*\n * Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Before;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.logging.Level;\n\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic abstract class AbstractEventBusTest {\n    /** Activates long(er) running tests e.g. testing multi-threading more thoroughly.  */\n    protected static final boolean LONG_TESTS = false;\n\n    protected EventBus eventBus;\n\n    protected final AtomicInteger eventCount = new AtomicInteger();\n    protected final List<Object> eventsReceived;\n\n    protected volatile Object lastEvent;\n    protected volatile Thread lastThread;\n\n    public AbstractEventBusTest() {\n        this(false);\n    }\n\n    public AbstractEventBusTest(boolean collectEventsReceived) {\n        if (collectEventsReceived) {\n            eventsReceived = new CopyOnWriteArrayList<Object>();\n        } else {\n            eventsReceived = null;\n        }\n    }\n\n    @Before\n    public void setUpBase() throws Exception {\n        EventBus.clearCaches();\n        eventBus = new EventBus();\n    }\n\n    protected void waitForEventCount(int expectedCount, int maxMillis) {\n        for (int i = 0; i < maxMillis; i++) {\n            int currentCount = eventCount.get();\n            if (currentCount == expectedCount) {\n                break;\n            } else if (currentCount > expectedCount) {\n                fail(\"Current count (\" + currentCount + \") is already higher than expected count (\" + expectedCount\n                        + \")\");\n            } else {\n                try {\n                    Thread.sleep(1);\n                } catch (InterruptedException e) {\n                    throw new RuntimeException(e);\n                }\n            }\n        }\n        assertEquals(expectedCount, eventCount.get());\n    }\n\n    protected void trackEvent(Object event) {\n        lastEvent = event;\n        lastThread = Thread.currentThread();\n        if (eventsReceived != null) {\n            eventsReceived.add(event);\n        }\n        // Must the the last one because we wait for this\n        eventCount.incrementAndGet();\n    }\n\n    protected void assertEventCount(int expectedEventCount) {\n        assertEquals(expectedEventCount, eventCount.intValue());\n    }\n    \n    protected void countDownAndAwaitLatch(CountDownLatch latch, long seconds) {\n        latch.countDown();\n        awaitLatch(latch, seconds);\n    }\n\n    protected void awaitLatch(CountDownLatch latch, long seconds) {\n        try {\n            assertTrue(latch.await(seconds, TimeUnit.SECONDS));\n        } catch (InterruptedException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    protected void log(String msg) {\n        eventBus.getLogger().log(Level.FINE, msg);\n    }\n\n    protected void log(String msg, Throwable e) {\n        eventBus.getLogger().log(Level.FINE, msg, e);\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBasicTest.java",
    "content": "/*\n * Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/**\n * @author Markus Junginger, greenrobot\n */\n@SuppressWarnings({\"WeakerAccess\", \"UnusedParameters\", \"unused\"})\npublic class EventBusBasicTest extends AbstractEventBusTest {\n\n    public static class WithIndex extends EventBusBasicTest {\n        @Test\n        public void dummy() {\n        }\n\n    }\n\n    private String lastStringEvent;\n    private int countStringEvent;\n    private int countIntEvent;\n    private int lastIntEvent;\n    private int countMyEventExtended;\n    private int countMyEvent;\n    private int countMyEvent2;\n\n    @Test\n    public void testRegisterAndPost() {\n        // Use an activity to test real life performance\n        StringEventSubscriber stringEventSubscriber = new StringEventSubscriber();\n        String event = \"Hello\";\n\n        long start = System.currentTimeMillis();\n        eventBus.register(stringEventSubscriber);\n        long time = System.currentTimeMillis() - start;\n        log(\"Registered in \" + time + \"ms\");\n\n        eventBus.post(event);\n\n        assertEquals(event, stringEventSubscriber.lastStringEvent);\n    }\n\n    @Test\n    public void testPostWithoutSubscriber() {\n        eventBus.post(\"Hello\");\n    }\n\n    @Test\n    public void testUnregisterWithoutRegister() {\n        // Results in a warning without throwing\n        eventBus.unregister(this);\n    }\n\n    // This will throw \"out of memory\" if subscribers are leaked\n    @Test\n    public void testUnregisterNotLeaking() {\n        int heapMBytes = (int) (Runtime.getRuntime().maxMemory() / (1024L * 1024L));\n        for (int i = 0; i < heapMBytes * 2; i++) {\n            @SuppressWarnings(\"unused\")\n            EventBusBasicTest subscriber = new EventBusBasicTest() {\n                byte[] expensiveObject = new byte[1024 * 1024];\n            };\n            eventBus.register(subscriber);\n            eventBus.unregister(subscriber);\n            log(\"Iteration \" + i + \" / max heap: \" + heapMBytes);\n        }\n    }\n\n    @Test\n    public void testRegisterTwice() {\n        eventBus.register(this);\n        try {\n            eventBus.register(this);\n            fail(\"Did not throw\");\n        } catch (RuntimeException expected) {\n            // OK\n        }\n    }\n\n    @Test\n    public void testIsRegistered() {\n        assertFalse(eventBus.isRegistered(this));\n        eventBus.register(this);\n        assertTrue(eventBus.isRegistered(this));\n        eventBus.unregister(this);\n        assertFalse(eventBus.isRegistered(this));\n    }\n\n    @Test\n    public void testPostWithTwoSubscriber() {\n        EventBusBasicTest test2 = new EventBusBasicTest();\n        eventBus.register(this);\n        eventBus.register(test2);\n        String event = \"Hello\";\n        eventBus.post(event);\n        assertEquals(event, lastStringEvent);\n        assertEquals(event, test2.lastStringEvent);\n    }\n\n    @Test\n    public void testPostMultipleTimes() {\n        eventBus.register(this);\n        MyEvent event = new MyEvent();\n        int count = 1000;\n        long start = System.currentTimeMillis();\n        // Debug.startMethodTracing(\"testPostMultipleTimes\" + count);\n        for (int i = 0; i < count; i++) {\n            eventBus.post(event);\n        }\n        // Debug.stopMethodTracing();\n        long time = System.currentTimeMillis() - start;\n        log(\"Posted \" + count + \" events in \" + time + \"ms\");\n        assertEquals(count, countMyEvent);\n    }\n\n    @Test\n    public void testMultipleSubscribeMethodsForEvent() {\n        eventBus.register(this);\n        MyEvent event = new MyEvent();\n        eventBus.post(event);\n        assertEquals(1, countMyEvent);\n        assertEquals(1, countMyEvent2);\n    }\n\n    @Test\n    public void testPostAfterUnregister() {\n        eventBus.register(this);\n        eventBus.unregister(this);\n        eventBus.post(\"Hello\");\n        assertNull(lastStringEvent);\n    }\n\n    @Test\n    public void testRegisterAndPostTwoTypes() {\n        eventBus.register(this);\n        eventBus.post(42);\n        eventBus.post(\"Hello\");\n        assertEquals(1, countIntEvent);\n        assertEquals(1, countStringEvent);\n        assertEquals(42, lastIntEvent);\n        assertEquals(\"Hello\", lastStringEvent);\n    }\n\n    @Test\n    public void testRegisterUnregisterAndPostTwoTypes() {\n        eventBus.register(this);\n        eventBus.unregister(this);\n        eventBus.post(42);\n        eventBus.post(\"Hello\");\n        assertEquals(0, countIntEvent);\n        assertEquals(0, lastIntEvent);\n        assertEquals(0, countStringEvent);\n    }\n\n    @Test\n    public void testPostOnDifferentEventBus() {\n        eventBus.register(this);\n        new EventBus().post(\"Hello\");\n        assertEquals(0, countStringEvent);\n    }\n\n    @Test\n    public void testPostInEventHandler() {\n        RepostInteger reposter = new RepostInteger();\n        eventBus.register(reposter);\n        eventBus.register(this);\n        eventBus.post(1);\n        assertEquals(10, countIntEvent);\n        assertEquals(10, lastIntEvent);\n        assertEquals(10, reposter.countEvent);\n        assertEquals(10, reposter.lastEvent);\n    }\n\n    @Test\n    public void testHasSubscriberForEvent() {\n        assertFalse(eventBus.hasSubscriberForEvent(String.class));\n\n        eventBus.register(this);\n        assertTrue(eventBus.hasSubscriberForEvent(String.class));\n\n        eventBus.unregister(this);\n        assertFalse(eventBus.hasSubscriberForEvent(String.class));\n    }\n\n    @Test\n    public void testHasSubscriberForEventSuperclass() {\n        assertFalse(eventBus.hasSubscriberForEvent(String.class));\n\n        Object subscriber = new ObjectSubscriber();\n        eventBus.register(subscriber);\n        assertTrue(eventBus.hasSubscriberForEvent(String.class));\n\n        eventBus.unregister(subscriber);\n        assertFalse(eventBus.hasSubscriberForEvent(String.class));\n    }\n\n    @Test\n    public void testHasSubscriberForEventImplementedInterface() {\n        assertFalse(eventBus.hasSubscriberForEvent(String.class));\n\n        Object subscriber = new CharSequenceSubscriber();\n        eventBus.register(subscriber);\n        assertTrue(eventBus.hasSubscriberForEvent(CharSequence.class));\n        assertTrue(eventBus.hasSubscriberForEvent(String.class));\n\n        eventBus.unregister(subscriber);\n        assertFalse(eventBus.hasSubscriberForEvent(CharSequence.class));\n        assertFalse(eventBus.hasSubscriberForEvent(String.class));\n    }\n\n    @Subscribe\n    public void onEvent(String event) {\n        lastStringEvent = event;\n        countStringEvent++;\n    }\n\n    @Subscribe\n    public void onEvent(Integer event) {\n        lastIntEvent = event;\n        countIntEvent++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEvent event) {\n        countMyEvent++;\n    }\n\n    @Subscribe\n    public void onEvent2(MyEvent event) {\n        countMyEvent2++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEventExtended event) {\n        countMyEventExtended++;\n    }\n\n    public static class StringEventSubscriber {\n        public String lastStringEvent;\n\n        @Subscribe\n        public void onEvent(String event) {\n            lastStringEvent = event;\n        }\n    }\n\n    public static class CharSequenceSubscriber {\n        @Subscribe\n        public void onEvent(CharSequence event) {\n        }\n    }\n\n    public static class ObjectSubscriber {\n        @Subscribe\n        public void onEvent(Object event) {\n        }\n    }\n\n    public class MyEvent {\n    }\n\n    public class MyEventExtended extends MyEvent {\n    }\n\n    public class RepostInteger {\n        public int lastEvent;\n        public int countEvent;\n\n        @Subscribe\n        public void onEvent(Integer event) {\n            lastEvent = event;\n            countEvent++;\n            assertEquals(countEvent, event.intValue());\n\n            if (event < 10) {\n                int countIntEventBefore = countEvent;\n                eventBus.post(event + 1);\n                // All our post calls will just enqueue the event, so check count is unchanged\n                assertEquals(countIntEventBefore, countIntEventBefore);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport static org.junit.Assert.fail;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusBuilderTest extends AbstractEventBusTest {\n\n    @Test\n    public void testThrowSubscriberException() {\n        eventBus = EventBus.builder().throwSubscriberException(true).build();\n        eventBus.register(new SubscriberExceptionEventTracker());\n        eventBus.register(new ThrowingSubscriber());\n        try {\n            eventBus.post(\"Foo\");\n            fail(\"Should have thrown\");\n        } catch (EventBusException e) {\n            // Expected\n        }\n    }\n\n    @Test\n    public void testDoNotSendSubscriberExceptionEvent() {\n        eventBus = EventBus.builder().logSubscriberExceptions(false).sendSubscriberExceptionEvent(false).build();\n        eventBus.register(new SubscriberExceptionEventTracker());\n        eventBus.register(new ThrowingSubscriber());\n        eventBus.post(\"Foo\");\n        assertEventCount(0);\n    }\n\n    @Test\n    public void testDoNotSendNoSubscriberEvent() {\n        eventBus = EventBus.builder().logNoSubscriberMessages(false).sendNoSubscriberEvent(false).build();\n        eventBus.register(new NoSubscriberEventTracker());\n        eventBus.post(\"Foo\");\n        assertEventCount(0);\n    }\n\n    @Test\n    public void testInstallDefaultEventBus() {\n        EventBusBuilder builder = EventBus.builder();\n        try {\n            // Either this should throw when another unit test got the default event bus...\n            eventBus = builder.installDefaultEventBus();\n            Assert.assertEquals(eventBus, EventBus.getDefault());\n\n            // ...or this should throw\n            eventBus = builder.installDefaultEventBus();\n            fail(\"Should have thrown\");\n        } catch (EventBusException e) {\n            // Expected\n        }\n    }\n\n    @Test\n    public void testEventInheritance() {\n        eventBus = EventBus.builder().eventInheritance(false).build();\n        eventBus.register(new ThrowingSubscriber());\n        eventBus.post(\"Foo\");\n    }\n\n    public class SubscriberExceptionEventTracker {\n        @Subscribe\n        public void onEvent(SubscriberExceptionEvent event) {\n            trackEvent(event);\n        }\n    }\n\n    public class NoSubscriberEventTracker {\n        @Subscribe\n        public void onEvent(NoSubscriberEvent event) {\n            trackEvent(event);\n        }\n    }\n\n    public class ThrowingSubscriber {\n        @Subscribe\n        public void onEvent(Object event) {\n            throw new RuntimeException();\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport java.util.concurrent.CountDownLatch;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.fail;\n\npublic class EventBusCancelEventDeliveryTest extends AbstractEventBusTest {\n\n    Throwable failed;\n\n    @Test\n    public void testCancel() {\n        Subscriber canceler = new Subscriber(1, true);\n        eventBus.register(new Subscriber(0, false));\n        eventBus.register(canceler);\n        eventBus.register(new Subscriber(0, false));\n        eventBus.post(\"42\");\n        assertEquals(1, eventCount.intValue());\n\n        eventBus.unregister(canceler);\n        eventBus.post(\"42\");\n        assertEquals(1 + 2, eventCount.intValue());\n    }\n\n    @Test\n    public void testCancelInBetween() {\n        eventBus.register(new Subscriber(2, true));\n        eventBus.register(new Subscriber(1, false));\n        eventBus.register(new Subscriber(3, false));\n        eventBus.post(\"42\");\n        assertEquals(2, eventCount.intValue());\n    }\n\n    @Test\n    public void testCancelOutsideEventHandler() {\n        try {\n            eventBus.cancelEventDelivery(this);\n            fail(\"Should have thrown\");\n        } catch (EventBusException e) {\n            // Expected\n        }\n    }\n\n    @Test\n    public void testCancelWrongEvent() {\n        eventBus.register(new SubscriberCancelOtherEvent());\n        eventBus.post(\"42\");\n        assertEquals(0, eventCount.intValue());\n        assertNotNull(failed);\n    }\n\n    public class Subscriber {\n        private final int prio;\n        private final boolean cancel;\n\n        public Subscriber(int prio, boolean cancel) {\n            this.prio = prio;\n            this.cancel = cancel;\n        }\n\n        @Subscribe\n        public void onEvent(String event) {\n            handleEvent(event, 0);\n        }\n\n        @Subscribe(priority = 1)\n        public void onEvent1(String event) {\n            handleEvent(event, 1);\n        }\n\n        @Subscribe(priority = 2)\n        public void onEvent2(String event) {\n            handleEvent(event, 2);\n        }\n\n        @Subscribe(priority = 3)\n        public void onEvent3(String event) {\n            handleEvent(event, 3);\n        }\n\n        private void handleEvent(String event, int prio) {\n            if(this.prio == prio) {\n                trackEvent(event);\n                if (cancel) {\n                    eventBus.cancelEventDelivery(event);\n                }\n            }\n        }\n    }\n\n    public class SubscriberCancelOtherEvent {\n        @Subscribe\n        public void onEvent(String event) {\n            try {\n                eventBus.cancelEventDelivery(this);\n            } catch (EventBusException e) {\n                failed = e;\n            }\n        }\n    }\n\n    public class SubscriberMainThread {\n        final CountDownLatch done = new CountDownLatch(1);\n\n        @Subscribe(threadMode = ThreadMode.MAIN)\n        public void onEventMainThread(String event) {\n            try {\n                eventBus.cancelEventDelivery(event);\n            } catch (EventBusException e) {\n                failed = e;\n            }\n            done.countDown();\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\n\npublic class EventBusFallbackToReflectionTest extends AbstractEventBusTest {\n    private class PrivateEvent {\n    }\n\n    public class PublicClass {\n        @Subscribe\n        public void onEvent(Object any) {\n            trackEvent(any);\n        }\n    }\n\n    private class PrivateClass {\n        @Subscribe\n        public void onEvent(Object any) {\n            trackEvent(any);\n        }\n    }\n\n    public class PublicWithPrivateSuperClass extends PrivateClass {\n        @Subscribe\n        public void onEvent(String any) {\n            trackEvent(any);\n        }\n    }\n\n    public class PublicClassWithPrivateEvent {\n        @Subscribe\n        public void onEvent(PrivateEvent any) {\n            trackEvent(any);\n        }\n    }\n\n    public class PublicClassWithPublicAndPrivateEvent {\n        @Subscribe\n        public void onEvent(String any) {\n            trackEvent(any);\n        }\n\n        @Subscribe\n        public void onEvent(PrivateEvent any) {\n            trackEvent(any);\n        }\n    }\n\n    public class PublicWithPrivateEventInSuperclass extends PublicClassWithPrivateEvent {\n        @Subscribe\n        public void onEvent(Object any) {\n            trackEvent(any);\n        }\n    }\n\n    public EventBusFallbackToReflectionTest() {\n        super(true);\n    }\n\n    @Test\n    public void testAnonymousSubscriberClass() {\n        Object subscriber = new Object() {\n            @Subscribe\n            public void onEvent(String event) {\n                trackEvent(event);\n            }\n        };\n        eventBus.register(subscriber);\n\n        eventBus.post(\"Hello\");\n        assertEquals(\"Hello\", lastEvent);\n        assertEquals(1, eventsReceived.size());\n    }\n\n    @Test\n    public void testAnonymousSubscriberClassWithPublicSuperclass() {\n        Object subscriber = new PublicClass() {\n            @Subscribe\n            public void onEvent(String event) {\n                trackEvent(event);\n            }\n        };\n        eventBus.register(subscriber);\n\n        eventBus.post(\"Hello\");\n        assertEquals(\"Hello\", lastEvent);\n        assertEquals(2, eventsReceived.size());\n    }\n\n    @Test\n    public void testAnonymousSubscriberClassWithPrivateSuperclass() {\n        eventBus.register(new PublicWithPrivateSuperClass());\n        eventBus.post(\"Hello\");\n        assertEquals(\"Hello\", lastEvent);\n        assertEquals(2, eventsReceived.size());\n    }\n\n    @Test\n    public void testSubscriberClassWithPrivateEvent() {\n        eventBus.register(new PublicClassWithPrivateEvent());\n        PrivateEvent privateEvent = new PrivateEvent();\n        eventBus.post(privateEvent);\n        assertEquals(privateEvent, lastEvent);\n        assertEquals(1, eventsReceived.size());\n    }\n\n    @Test\n    public void testSubscriberClassWithPublicAndPrivateEvent() {\n        eventBus.register(new PublicClassWithPublicAndPrivateEvent());\n\n        eventBus.post(\"Hello\");\n        assertEquals(\"Hello\", lastEvent);\n        assertEquals(1, eventsReceived.size());\n\n        PrivateEvent privateEvent = new PrivateEvent();\n        eventBus.post(privateEvent);\n        assertEquals(privateEvent, lastEvent);\n        assertEquals(2, eventsReceived.size());\n    }\n\n    @Test\n    public void testSubscriberExtendingClassWithPrivateEvent() {\n        eventBus.register(new PublicWithPrivateEventInSuperclass());\n        PrivateEvent privateEvent = new PrivateEvent();\n        eventBus.post(privateEvent);\n        assertEquals(privateEvent, lastEvent);\n        assertEquals(2, eventsReceived.size());\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusGenericsTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\npublic class EventBusGenericsTest extends AbstractEventBusTest {\n    public static class GenericEvent<T> {\n        T value;\n    }\n\n    public class GenericEventSubscriber<T> {\n        @Subscribe\n        public void onGenericEvent(GenericEvent<T> event) {\n            trackEvent(event);\n        }\n    }\n\n    public class FullGenericEventSubscriber<T> {\n        @Subscribe\n        public void onGenericEvent(T event) {\n            trackEvent(event);\n        }\n    }\n\n    public class GenericNumberEventSubscriber<T extends Number> {\n        @Subscribe\n        public void onGenericEvent(T event) {\n            trackEvent(event);\n        }\n    }\n\n    public class GenericFloatEventSubscriber extends GenericNumberEventSubscriber<Float> {\n    }\n\n    @Test\n    public void testGenericEventAndSubscriber() {\n        GenericEventSubscriber<IntTestEvent> genericSubscriber = new GenericEventSubscriber<IntTestEvent>();\n        eventBus.register(genericSubscriber);\n        eventBus.post(new GenericEvent<Integer>());\n        assertEventCount(1);\n    }\n\n    @Test\n    public void testGenericEventAndSubscriber_TypeErasure() {\n        FullGenericEventSubscriber<IntTestEvent> genericSubscriber = new FullGenericEventSubscriber<IntTestEvent>();\n        eventBus.register(genericSubscriber);\n        eventBus.post(new IntTestEvent(42));\n        eventBus.post(\"Type erasure!\");\n        assertEventCount(2);\n    }\n\n    @Test\n    public void testGenericEventAndSubscriber_BaseType() {\n        GenericNumberEventSubscriber<Float> genericSubscriber = new GenericNumberEventSubscriber<>();\n        eventBus.register(genericSubscriber);\n        eventBus.post(new Float(42));\n        eventBus.post(new Double(23));\n        assertEventCount(2);\n        eventBus.post(\"Not the same base type\");\n        assertEventCount(2);\n    }\n\n    @Test\n    public void testGenericEventAndSubscriber_Subclass() {\n        GenericFloatEventSubscriber genericSubscriber = new GenericFloatEventSubscriber();\n        eventBus.register(genericSubscriber);\n        eventBus.post(new Float(42));\n        eventBus.post(new Double(77));\n        assertEventCount(2);\n        eventBus.post(\"Not the same base type\");\n        assertEventCount(2);\n    }\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusIndexTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus;\n\nimport org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\nimport org.greenrobot.eventbus.meta.SubscriberInfo;\nimport org.greenrobot.eventbus.meta.SubscriberInfoIndex;\nimport org.greenrobot.eventbus.meta.SubscriberMethodInfo;\nimport org.junit.Assert;\nimport org.junit.Test;\n\npublic class EventBusIndexTest {\n    private String value;\n\n    /** Ensures the index is actually used and no reflection fall-back kicks in. */\n    @Test\n    public void testManualIndexWithoutAnnotation() {\n        SubscriberInfoIndex index = new SubscriberInfoIndex() {\n\n            @Override\n            public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {\n                Assert.assertEquals(EventBusIndexTest.class, subscriberClass);\n                SubscriberMethodInfo[] methodInfos = {\n                        new SubscriberMethodInfo(\"someMethodWithoutAnnotation\", String.class)\n                };\n                return new SimpleSubscriberInfo(EventBusIndexTest.class, false, methodInfos);\n            }\n        };\n\n        EventBus eventBus = EventBus.builder().addIndex(index).build();\n        eventBus.register(this);\n        eventBus.post(\"Yepp\");\n        eventBus.unregister(this);\n        Assert.assertEquals(\"Yepp\", value);\n    }\n\n    public void someMethodWithoutAnnotation(String value) {\n        this.value = value;\n    }\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java",
    "content": "package org.greenrobot.eventbus;\n\n// Need to use upper class or Android test runner does not pick it up\npublic class EventBusInheritanceDisabledSubclassNoMethod extends EventBusInheritanceDisabledTest {\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java",
    "content": "package org.greenrobot.eventbus;\n\nimport org.junit.Ignore;\n\n// Need to use upper class or Android test runner does not pick it up\npublic class EventBusInheritanceDisabledSubclassTest extends EventBusInheritanceDisabledTest {\n\n    int countMyEventOverwritten;\n\n    @Subscribe\n    public void onEvent(MyEvent event) {\n        countMyEventOverwritten++;\n    }\n\n    @Override\n    @Ignore\n    public void testEventClassHierarchy() {\n        // TODO fix test in super, then remove this\n    }\n}"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static junit.framework.Assert.assertEquals;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusInheritanceDisabledTest {\n\n    protected EventBus eventBus;\n\n    protected int countMyEventExtended;\n    protected int countMyEvent;\n    protected int countObjectEvent;\n    private int countMyEventInterface;\n    private int countMyEventInterfaceExtended;\n\n    @Before\n    public void setUp() throws Exception {\n        eventBus = EventBus.builder().eventInheritance(false).build();\n    }\n\n    @Test\n    public void testEventClassHierarchy() {\n        eventBus.register(this);\n\n        eventBus.post(\"Hello\");\n        assertEquals(0, countObjectEvent);\n\n        eventBus.post(new MyEvent());\n        assertEquals(0, countObjectEvent);\n        assertEquals(1, countMyEvent);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(0, countObjectEvent);\n        assertEquals(1, countMyEvent);\n        assertEquals(1, countMyEventExtended);\n    }\n\n    @Test\n    public void testEventClassHierarchySticky() {\n        eventBus.postSticky(\"Hello\");\n        eventBus.postSticky(new MyEvent());\n        eventBus.postSticky(new MyEventExtended());\n        eventBus.register(new StickySubscriber());\n        assertEquals(1, countMyEventExtended);\n        assertEquals(1, countMyEvent);\n        assertEquals(0, countObjectEvent);\n    }\n\n    @Test\n    public void testEventInterfaceHierarchy() {\n        eventBus.register(this);\n\n        eventBus.post(new MyEvent());\n        assertEquals(0, countMyEventInterface);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(0, countMyEventInterface);\n        assertEquals(0, countMyEventInterfaceExtended);\n    }\n\n    @Test\n    public void testEventSuperInterfaceHierarchy() {\n        eventBus.register(this);\n\n        eventBus.post(new MyEventInterfaceExtended() {\n        });\n        assertEquals(0, countMyEventInterface);\n        assertEquals(0, countMyEventInterfaceExtended);\n    }\n\n    @Test\n    public void testSubscriberClassHierarchy() {\n        EventBusInheritanceDisabledSubclassTest\n                subscriber = new EventBusInheritanceDisabledSubclassTest();\n        eventBus.register(subscriber);\n\n        eventBus.post(\"Hello\");\n        assertEquals(0, subscriber.countObjectEvent);\n\n        eventBus.post(new MyEvent());\n        assertEquals(0, subscriber.countObjectEvent);\n        assertEquals(0, subscriber.countMyEvent);\n        assertEquals(1, subscriber.countMyEventOverwritten);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(0, subscriber.countObjectEvent);\n        assertEquals(0, subscriber.countMyEvent);\n        assertEquals(1, subscriber.countMyEventExtended);\n        assertEquals(1, subscriber.countMyEventOverwritten);\n    }\n\n    @Test\n    public void testSubscriberClassHierarchyWithoutNewSubscriberMethod() {\n        EventBusInheritanceDisabledSubclassNoMethod\n                subscriber = new EventBusInheritanceDisabledSubclassNoMethod();\n        eventBus.register(subscriber);\n\n        eventBus.post(\"Hello\");\n        assertEquals(0, subscriber.countObjectEvent);\n\n        eventBus.post(new MyEvent());\n        assertEquals(0, subscriber.countObjectEvent);\n        assertEquals(1, subscriber.countMyEvent);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(0, subscriber.countObjectEvent);\n        assertEquals(1, subscriber.countMyEvent);\n        assertEquals(1, subscriber.countMyEventExtended);\n    }\n\n    @Subscribe\n    public void onEvent(Object event) {\n        countObjectEvent++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEvent event) {\n        countMyEvent++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEventExtended event) {\n        countMyEventExtended++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEventInterface event) {\n        countMyEventInterface++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEventInterfaceExtended event) {\n        countMyEventInterfaceExtended++;\n    }\n\n    public static interface MyEventInterface {\n    }\n\n    public static class MyEvent implements MyEventInterface {\n    }\n\n    public static interface MyEventInterfaceExtended extends MyEventInterface {\n    }\n\n    public static class MyEventExtended extends MyEvent implements MyEventInterfaceExtended {\n    }\n\n    public class StickySubscriber {\n        @Subscribe(sticky = true)\n        public void onEvent(Object event) {\n            countObjectEvent++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEvent event) {\n            countMyEvent++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEventExtended event) {\n            countMyEventExtended++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEventInterface event) {\n            countMyEventInterface++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEventInterfaceExtended event) {\n            countMyEventInterfaceExtended++;\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java",
    "content": "package org.greenrobot.eventbus;\n\n// Need to use upper class or Android test runner does not pick it up\npublic class EventBusInheritanceSubclassNoMethodTest extends EventBusInheritanceTest {\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java",
    "content": "package org.greenrobot.eventbus;\n\nimport org.junit.Ignore;\n\n// Need to use upper class or Android test runner does not pick it up\npublic class EventBusInheritanceSubclassTest extends EventBusInheritanceTest {\n    int countMyEventOverwritten;\n\n    @Subscribe\n    public void onEvent(MyEvent event) {\n        countMyEventOverwritten++;\n    }\n\n    @Override\n    @Ignore\n    public void testEventClassHierarchy() {\n        // TODO fix test in super, then remove this\n    }\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusInheritanceTest {\n\n    protected EventBus eventBus;\n\n    protected int countMyEventExtended;\n    protected int countMyEvent;\n    protected int countObjectEvent;\n    private int countMyEventInterface;\n    private int countMyEventInterfaceExtended;\n\n    @Before\n    public void setUp() throws Exception {\n        eventBus = new EventBus();\n    }\n\n    @Test\n    public void testEventClassHierarchy() {\n        eventBus.register(this);\n\n        eventBus.post(\"Hello\");\n        assertEquals(1, countObjectEvent);\n\n        eventBus.post(new MyEvent());\n        assertEquals(2, countObjectEvent);\n        assertEquals(1, countMyEvent);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(3, countObjectEvent);\n        assertEquals(2, countMyEvent);\n        assertEquals(1, countMyEventExtended);\n    }\n\n    @Test\n    public void testEventClassHierarchySticky() {\n        eventBus.postSticky(\"Hello\");\n        eventBus.postSticky(new MyEvent());\n        eventBus.postSticky(new MyEventExtended());\n        eventBus.register(new StickySubscriber());\n        assertEquals(1, countMyEventExtended);\n        assertEquals(2, countMyEvent);\n        assertEquals(3, countObjectEvent);\n    }\n\n    @Test\n    public void testEventInterfaceHierarchy() {\n        eventBus.register(this);\n\n        eventBus.post(new MyEvent());\n        assertEquals(1, countMyEventInterface);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(2, countMyEventInterface);\n        assertEquals(1, countMyEventInterfaceExtended);\n    }\n\n    @Test\n    public void testEventSuperInterfaceHierarchy() {\n        eventBus.register(this);\n\n        eventBus.post(new MyEventInterfaceExtended() {\n        });\n        assertEquals(1, countMyEventInterface);\n        assertEquals(1, countMyEventInterfaceExtended);\n    }\n\n    @Test\n    public void testSubscriberClassHierarchy() {\n        EventBusInheritanceSubclassTest subscriber = new EventBusInheritanceSubclassTest();\n        eventBus.register(subscriber);\n\n        eventBus.post(\"Hello\");\n        assertEquals(1, subscriber.countObjectEvent);\n\n        eventBus.post(new MyEvent());\n        assertEquals(2, subscriber.countObjectEvent);\n        assertEquals(0, subscriber.countMyEvent);\n        assertEquals(1, subscriber.countMyEventOverwritten);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(3, subscriber.countObjectEvent);\n        assertEquals(0, subscriber.countMyEvent);\n        assertEquals(1, subscriber.countMyEventExtended);\n        assertEquals(2, subscriber.countMyEventOverwritten);\n    }\n\n    @Test\n    public void testSubscriberClassHierarchyWithoutNewSubscriberMethod() {\n        EventBusInheritanceSubclassNoMethodTest\n                subscriber = new EventBusInheritanceSubclassNoMethodTest();\n        eventBus.register(subscriber);\n\n        eventBus.post(\"Hello\");\n        assertEquals(1, subscriber.countObjectEvent);\n\n        eventBus.post(new MyEvent());\n        assertEquals(2, subscriber.countObjectEvent);\n        assertEquals(1, subscriber.countMyEvent);\n\n        eventBus.post(new MyEventExtended());\n        assertEquals(3, subscriber.countObjectEvent);\n        assertEquals(2, subscriber.countMyEvent);\n        assertEquals(1, subscriber.countMyEventExtended);\n    }\n\n    @Subscribe\n    public void onEvent(Object event) {\n        countObjectEvent++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEvent event) {\n        countMyEvent++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEventExtended event) {\n        countMyEventExtended++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEventInterface event) {\n        countMyEventInterface++;\n    }\n\n    @Subscribe\n    public void onEvent(MyEventInterfaceExtended event) {\n        countMyEventInterfaceExtended++;\n    }\n\n    public static interface MyEventInterface {\n    }\n\n    public static class MyEvent implements MyEventInterface {\n    }\n\n    public static interface MyEventInterfaceExtended extends MyEventInterface {\n    }\n\n    public static class MyEventExtended extends MyEvent implements MyEventInterfaceExtended {\n    }\n\n    public class StickySubscriber {\n        @Subscribe(sticky = true)\n        public void onEvent(Object event) {\n            countObjectEvent++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEvent event) {\n            countMyEvent++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEventExtended event) {\n            countMyEventExtended++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEventInterface event) {\n            countMyEventInterface++;\n        }\n\n        @Subscribe(sticky = true)\n        public void onEvent(MyEventInterfaceExtended event) {\n            countMyEventInterfaceExtended++;\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusMultithreadedTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.Assert.assertEquals;\n\npublic class EventBusMultithreadedTest extends AbstractEventBusTest {\n\n    static final int COUNT = LONG_TESTS ? 100000 : 1000;\n\n    final AtomicInteger countStringEvent = new AtomicInteger();\n    final AtomicInteger countIntegerEvent = new AtomicInteger();\n    final AtomicInteger countObjectEvent = new AtomicInteger();\n    final AtomicInteger countIntTestEvent = new AtomicInteger();\n\n    String lastStringEvent;\n    Integer lastIntegerEvent;\n\n    IntTestEvent lastIntTestEvent;\n\n    @Test\n    public void testPost01Thread() throws InterruptedException {\n        runThreadsSingleEventType(1);\n    }\n\n    @Test\n    public void testPost04Threads() throws InterruptedException {\n        runThreadsSingleEventType(4);\n    }\n\n    @Test\n    public void testPost40Threads() throws InterruptedException {\n        runThreadsSingleEventType(40);\n    }\n\n    @Test\n    public void testPostMixedEventType01Thread() throws InterruptedException {\n        runThreadsMixedEventType(1);\n    }\n\n    @Test\n    public void testPostMixedEventType04Threads() throws InterruptedException {\n        runThreadsMixedEventType(4);\n    }\n\n    @Test\n    public void testPostMixedEventType40Threads() throws InterruptedException {\n        runThreadsMixedEventType(40);\n    }\n\n    private void runThreadsSingleEventType(int threadCount) throws InterruptedException {\n        int iterations = COUNT / threadCount;\n        eventBus.register(this);\n\n        CountDownLatch latch = new CountDownLatch(threadCount + 1);\n        List<PosterThread> threads = startThreads(latch, threadCount, iterations, \"Hello\");\n        long time = triggerAndWaitForThreads(threads, latch);\n\n        log(threadCount + \" threads posted \" + iterations + \" events each in \" + time + \"ms\");\n\n        waitForEventCount(COUNT * 2, 5000);\n\n        assertEquals(\"Hello\", lastStringEvent);\n        int expectedCount = threadCount * iterations;\n        assertEquals(expectedCount, countStringEvent.intValue());\n        assertEquals(expectedCount, countObjectEvent.intValue());\n    }\n\n    private void runThreadsMixedEventType(int threadCount) throws InterruptedException {\n        runThreadsMixedEventType(COUNT, threadCount);\n    }\n\n    void runThreadsMixedEventType(int count, int threadCount) throws InterruptedException {\n        eventBus.register(this);\n        int eventTypeCount = 3;\n        int iterations = count / threadCount / eventTypeCount;\n\n        CountDownLatch latch = new CountDownLatch(eventTypeCount * threadCount + 1);\n        List<PosterThread> threadsString = startThreads(latch, threadCount, iterations, \"Hello\");\n        List<PosterThread> threadsInteger = startThreads(latch, threadCount, iterations, 42);\n        List<PosterThread> threadsIntTestEvent = startThreads(latch, threadCount, iterations, new IntTestEvent(7));\n\n        List<PosterThread> threads = new ArrayList<PosterThread>();\n        threads.addAll(threadsString);\n        threads.addAll(threadsInteger);\n        threads.addAll(threadsIntTestEvent);\n        long time = triggerAndWaitForThreads(threads, latch);\n\n        log(threadCount * eventTypeCount + \" mixed threads posted \" + iterations + \" events each in \"\n                + time + \"ms\");\n\n        int expectedCountEach = threadCount * iterations;\n        int expectedCountTotal = expectedCountEach * eventTypeCount * 2;\n        waitForEventCount(expectedCountTotal, 5000);\n\n        assertEquals(\"Hello\", lastStringEvent);\n        assertEquals(42, lastIntegerEvent.intValue());\n        assertEquals(7, lastIntTestEvent.value);\n\n        assertEquals(expectedCountEach, countStringEvent.intValue());\n        assertEquals(expectedCountEach, countIntegerEvent.intValue());\n        assertEquals(expectedCountEach, countIntTestEvent.intValue());\n\n        assertEquals(expectedCountEach * eventTypeCount, countObjectEvent.intValue());\n    }\n\n    private long triggerAndWaitForThreads(List<PosterThread> threads, CountDownLatch latch) throws InterruptedException {\n        while (latch.getCount() != 1) {\n            // Let all other threads prepare and ensure this one is the last \n            Thread.sleep(1);\n        }\n        long start = System.currentTimeMillis();\n        latch.countDown();\n        for (PosterThread thread : threads) {\n            thread.join();\n        }\n        return System.currentTimeMillis() - start;\n    }\n\n    private List<PosterThread> startThreads(CountDownLatch latch, int threadCount, int iterations, Object eventToPost) {\n        List<PosterThread> threads = new ArrayList<PosterThread>(threadCount);\n        for (int i = 0; i < threadCount; i++) {\n            PosterThread thread = new PosterThread(latch, iterations, eventToPost);\n            thread.start();\n            threads.add(thread);\n        }\n        return threads;\n    }\n\n    @Subscribe(threadMode = ThreadMode.BACKGROUND)\n    public void onEventBackgroundThread(String event) {\n        lastStringEvent = event;\n        countStringEvent.incrementAndGet();\n        trackEvent(event);\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onEventMainThread(Integer event) {\n        lastIntegerEvent = event;\n        countIntegerEvent.incrementAndGet();\n        trackEvent(event);\n    }\n\n    @Subscribe(threadMode = ThreadMode.ASYNC)\n    public void onEventAsync(IntTestEvent event) {\n        countIntTestEvent.incrementAndGet();\n        lastIntTestEvent = event;\n        trackEvent(event);\n    }\n\n    @Subscribe\n    public void onEvent(Object event) {\n        countObjectEvent.incrementAndGet();\n        trackEvent(event);\n    }\n\n    class PosterThread extends Thread {\n\n        private final CountDownLatch startLatch;\n        private final int iterations;\n        private final Object eventToPost;\n\n        public PosterThread(CountDownLatch latch, int iterations, Object eventToPost) {\n            this.startLatch = latch;\n            this.iterations = iterations;\n            this.eventToPost = eventToPost;\n        }\n\n        @Override\n        public void run() {\n            startLatch.countDown();\n            try {\n                startLatch.await();\n            } catch (InterruptedException e) {\n                log(\"Unexpected interrupt\", e);\n            }\n\n            for (int i = 0; i < iterations; i++) {\n                eventBus.post(eventToPost);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertSame;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusNoSubscriberEventTest extends AbstractEventBusTest {\n\n    @Test\n    public void testNoSubscriberEvent() {\n        eventBus.register(this);\n        eventBus.post(\"Foo\");\n        assertEventCount(1);\n        assertEquals(NoSubscriberEvent.class, lastEvent.getClass());\n        NoSubscriberEvent noSub = (NoSubscriberEvent) lastEvent;\n        assertEquals(\"Foo\", noSub.originalEvent);\n        assertSame(eventBus, noSub.eventBus);\n    }\n\n    @Test\n    public void testNoSubscriberEventAfterUnregister() {\n        Object subscriber = new DummySubscriber();\n        eventBus.register(subscriber);\n        eventBus.unregister(subscriber);\n        testNoSubscriberEvent();\n    }\n\n    @Test\n    public void testBadNoSubscriberSubscriber() {\n        eventBus = EventBus.builder().logNoSubscriberMessages(false).build();\n        eventBus.register(this);\n        eventBus.register(new BadNoSubscriberSubscriber());\n        eventBus.post(\"Foo\");\n        assertEventCount(2);\n\n        assertEquals(SubscriberExceptionEvent.class, lastEvent.getClass());\n        NoSubscriberEvent noSub = (NoSubscriberEvent) ((SubscriberExceptionEvent) lastEvent).causingEvent;\n        assertEquals(\"Foo\", noSub.originalEvent);\n    }\n\n    @Subscribe\n    public void onEvent(NoSubscriberEvent event) {\n        trackEvent(event);\n    }\n\n    @Subscribe\n    public void onEvent(SubscriberExceptionEvent event) {\n        trackEvent(event);\n    }\n\n    public static class DummySubscriber {\n        @SuppressWarnings(\"unused\")\n        @Subscribe\n        public void onEvent(String dummy) {\n        }\n    }\n\n    public class BadNoSubscriberSubscriber {\n        @Subscribe\n        public void onEvent(NoSubscriberEvent event) {\n            throw new RuntimeException(\"I'm bad\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusOrderedSubscriptionsTest extends AbstractEventBusTest {\n\n    int lastPrio = Integer.MAX_VALUE;\n    final List<PrioSubscriber> registered = new ArrayList<PrioSubscriber>();\n    private String fail;\n\n    @Test\n    public void testOrdered() {\n        runTestOrdered(\"42\", false, 5);\n    }\n\n    @Test\n    public void testOrderedMainThread() {\n        runTestOrdered(new IntTestEvent(42), false, 3);\n    }\n\n    @Test\n    public void testOrderedBackgroundThread() {\n        runTestOrdered(Integer.valueOf(42), false, 3);\n    }\n\n    @Test\n    public void testOrderedSticky() {\n        runTestOrdered(\"42\", true, 5);\n    }\n\n    @Test\n    public void testOrderedMainThreadSticky() {\n        runTestOrdered(new IntTestEvent(42), true, 3);\n    }\n\n    @Test\n    public void testOrderedBackgroundThreadSticky() {\n        runTestOrdered(Integer.valueOf(42), true, 3);\n    }\n\n    protected void runTestOrdered(Object event, boolean sticky, int expectedEventCount) {\n        Object subscriber = sticky ? new PrioSubscriberSticky() : new PrioSubscriber();\n        eventBus.register(subscriber);\n        eventBus.post(event);\n\n        waitForEventCount(expectedEventCount, 10000);\n        assertEquals(null, fail);\n\n        eventBus.unregister(subscriber);\n    }\n\n    public final class PrioSubscriber {\n        @Subscribe(priority = 1)\n        public void onEventP1(String event) {\n            handleEvent(1, event);\n        }\n\n        @Subscribe(priority = -1)\n        public void onEventM1(String event) {\n            handleEvent(-1, event);\n        }\n\n        @Subscribe(priority = 0)\n        public void onEventP0(String event) {\n            handleEvent(0, event);\n        }\n\n        @Subscribe(priority = 10)\n        public void onEventP10(String event) {\n            handleEvent(10, event);\n        }\n\n        @Subscribe(priority = -100)\n        public void onEventM100(String event) {\n            handleEvent(-100, event);\n        }\n\n\n        @Subscribe(threadMode = ThreadMode.MAIN, priority = -1)\n        public void onEventMainThreadM1(IntTestEvent event) {\n            handleEvent(-1, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.MAIN)\n        public void onEventMainThreadP0(IntTestEvent event) {\n            handleEvent(0, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.MAIN, priority = 1)\n        public void onEventMainThreadP1(IntTestEvent event) {\n            handleEvent(1, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 1)\n        public void onEventBackgroundThreadP1(Integer event) {\n            handleEvent(1, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.BACKGROUND)\n        public void onEventBackgroundThreadP0(Integer event) {\n            handleEvent(0, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = -1)\n        public void onEventBackgroundThreadM1(Integer event) {\n            handleEvent(-1, event);\n        }\n\n        protected void handleEvent(int prio, Object event) {\n            if (prio > lastPrio) {\n                fail = \"Called prio \" + prio + \" after \" + lastPrio;\n            }\n            lastPrio = prio;\n\n            log(\"Subscriber \" + prio + \" got: \" + event);\n            trackEvent(event);\n        }\n\n    }\n\n    public final class PrioSubscriberSticky {\n        @Subscribe(priority = 1, sticky = true)\n        public void onEventP1(String event) {\n            handleEvent(1, event);\n        }\n\n\n        @Subscribe(priority = -1, sticky = true)\n        public void onEventM1(String event) {\n            handleEvent(-1, event);\n        }\n\n        @Subscribe(priority = 0, sticky = true)\n        public void onEventP0(String event) {\n            handleEvent(0, event);\n        }\n\n        @Subscribe(priority = 10, sticky = true)\n        public void onEventP10(String event) {\n            handleEvent(10, event);\n        }\n\n        @Subscribe(priority = -100, sticky = true)\n        public void onEventM100(String event) {\n            handleEvent(-100, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.MAIN, priority = -1, sticky = true)\n        public void onEventMainThreadM1(IntTestEvent event) {\n            handleEvent(-1, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)\n        public void onEventMainThreadP0(IntTestEvent event) {\n            handleEvent(0, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.MAIN, priority = 1, sticky = true)\n        public void onEventMainThreadP1(IntTestEvent event) {\n            handleEvent(1, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 1, sticky = true)\n        public void onEventBackgroundThreadP1(Integer event) {\n            handleEvent(1, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.BACKGROUND, sticky = true)\n        public void onEventBackgroundThreadP0(Integer event) {\n            handleEvent(0, event);\n        }\n\n        @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = -1, sticky = true)\n        public void onEventBackgroundThreadM1(Integer event) {\n            handleEvent(-1, event);\n        }\n\n        protected void handleEvent(int prio, Object event) {\n            if (prio > lastPrio) {\n                fail = \"Called prio \" + prio + \" after \" + lastPrio;\n            }\n            lastPrio = prio;\n\n            log(\"Subscriber \" + prio + \" got: \" + event);\n            trackEvent(event);\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\n\nimport static org.junit.Assert.fail;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusRegistrationRacingTest extends AbstractEventBusTest {\n\n    // On a Nexus 5, bad synchronization always failed on the first iteration or went well completely.\n    // So a high number of iterations do not guarantee a better probability of finding bugs.\n    private static final int ITERATIONS = LONG_TESTS ? 1000 : 10;\n    private static final int THREAD_COUNT = 16;\n\n    volatile CountDownLatch startLatch;\n    volatile CountDownLatch registeredLatch;\n    volatile CountDownLatch canUnregisterLatch;\n    volatile CountDownLatch unregisteredLatch;\n    \n    final Executor threadPool = Executors.newCachedThreadPool();\n\n    @Test\n    public void testRacingRegistrations() throws InterruptedException {\n        for (int i = 0; i < ITERATIONS; i++) {\n            startLatch = new CountDownLatch(THREAD_COUNT);\n            registeredLatch = new CountDownLatch(THREAD_COUNT);\n            canUnregisterLatch = new CountDownLatch(1);\n            unregisteredLatch = new CountDownLatch(THREAD_COUNT);\n            \n            List<SubscriberThread> threads = startThreads();\n            registeredLatch.await();\n            eventBus.post(\"42\");\n            canUnregisterLatch.countDown();\n            for (int t = 0; t < THREAD_COUNT; t++) {\n                int eventCount = threads.get(t).eventCount;\n                if (eventCount != 1) {\n                    fail(\"Failed in iteration \" + i + \": thread #\" + t + \" has event count of \" + eventCount);\n                }\n            }\n            // Wait for threads to be done\n            unregisteredLatch.await();\n        }\n    }\n\n    private List<SubscriberThread> startThreads() {\n        List<SubscriberThread> threads = new ArrayList<SubscriberThread>(THREAD_COUNT);\n        for (int i = 0; i < THREAD_COUNT; i++) {\n            SubscriberThread thread = new SubscriberThread();\n            threadPool.execute(thread);\n            threads.add(thread);\n        }\n        return threads;\n    }\n\n    public class SubscriberThread implements Runnable {\n        volatile int eventCount;\n\n        @Override\n        public void run() {\n            countDownAndAwaitLatch(startLatch, 10);\n            eventBus.register(this);\n            registeredLatch.countDown();\n            try {\n                canUnregisterLatch.await();\n            } catch (InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n            eventBus.unregister(this);\n            unregisteredLatch.countDown();\n        }\n\n        @Subscribe\n        public void onEvent(String event) {\n            eventCount++;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusStickyEventTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusStickyEventTest extends AbstractEventBusTest {\n\n    @Test\n    public void testPostSticky() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.register(this);\n        assertEquals(\"Sticky\", lastEvent);\n        assertEquals(Thread.currentThread(), lastThread);\n    }\n\n    @Test\n    public void testPostStickyTwoEvents() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.postSticky(new IntTestEvent(7));\n        eventBus.register(this);\n        assertEquals(2, eventCount.intValue());\n    }\n\n    @Test\n    public void testPostStickyTwoSubscribers() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.postSticky(new IntTestEvent(7));\n        eventBus.register(this);\n        StickyIntTestSubscriber subscriber2 = new StickyIntTestSubscriber();\n        eventBus.register(subscriber2);\n        assertEquals(3, eventCount.intValue());\n\n        eventBus.postSticky(\"Sticky\");\n        assertEquals(4, eventCount.intValue());\n\n        eventBus.postSticky(new IntTestEvent(8));\n        assertEquals(6, eventCount.intValue());\n    }\n\n    @Test\n    public void testPostStickyRegisterNonSticky() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.register(new NonStickySubscriber());\n        assertNull(lastEvent);\n        assertEquals(0, eventCount.intValue());\n    }\n\n    @Test\n    public void testPostNonStickyRegisterSticky() throws InterruptedException {\n        eventBus.post(\"NonSticky\");\n        eventBus.register(this);\n        assertNull(lastEvent);\n        assertEquals(0, eventCount.intValue());\n    }\n\n    @Test\n    public void testPostStickyTwice() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.postSticky(\"NewSticky\");\n        eventBus.register(this);\n        assertEquals(\"NewSticky\", lastEvent);\n    }\n\n    @Test\n    public void testPostStickyThenPostNormal() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.post(\"NonSticky\");\n        eventBus.register(this);\n        assertEquals(\"Sticky\", lastEvent);\n    }\n\n    @Test\n    public void testPostStickyWithRegisterAndUnregister() throws InterruptedException {\n        eventBus.register(this);\n        eventBus.postSticky(\"Sticky\");\n        assertEquals(\"Sticky\", lastEvent);\n\n        eventBus.unregister(this);\n        eventBus.register(this);\n        assertEquals(\"Sticky\", lastEvent);\n        assertEquals(2, eventCount.intValue());\n\n        eventBus.postSticky(\"NewSticky\");\n        assertEquals(3, eventCount.intValue());\n        assertEquals(\"NewSticky\", lastEvent);\n\n        eventBus.unregister(this);\n        eventBus.register(this);\n        assertEquals(4, eventCount.intValue());\n        assertEquals(\"NewSticky\", lastEvent);\n    }\n\n    @Test\n    public void testPostStickyAndGet() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        assertEquals(\"Sticky\", eventBus.getStickyEvent(String.class));\n    }\n\n    @Test\n    public void testPostStickyRemoveClass() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.removeStickyEvent(String.class);\n        assertNull(eventBus.getStickyEvent(String.class));\n        eventBus.register(this);\n        assertNull(lastEvent);\n        assertEquals(0, eventCount.intValue());\n    }\n\n    @Test\n    public void testPostStickyRemoveEvent() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        assertTrue(eventBus.removeStickyEvent(\"Sticky\"));\n        assertNull(eventBus.getStickyEvent(String.class));\n        eventBus.register(this);\n        assertNull(lastEvent);\n        assertEquals(0, eventCount.intValue());\n    }\n\n    @Test\n    public void testPostStickyRemoveAll() throws InterruptedException {\n        eventBus.postSticky(\"Sticky\");\n        eventBus.postSticky(new IntTestEvent(77));\n        eventBus.removeAllStickyEvents();\n        assertNull(eventBus.getStickyEvent(String.class));\n        assertNull(eventBus.getStickyEvent(IntTestEvent.class));\n        eventBus.register(this);\n        assertNull(lastEvent);\n        assertEquals(0, eventCount.intValue());\n    }\n\n    @Test\n    public void testRemoveStickyEventInSubscriber() throws InterruptedException {\n        eventBus.register(new RemoveStickySubscriber());\n        eventBus.postSticky(\"Sticky\");\n        eventBus.register(this);\n        assertNull(lastEvent);\n        assertEquals(0, eventCount.intValue());\n        assertNull(eventBus.getStickyEvent(String.class));\n    }\n\n    @Subscribe(sticky = true)\n    public void onEvent(String event) {\n        trackEvent(event);\n    }\n\n    @Subscribe(sticky = true)\n    public void onEvent(IntTestEvent event) {\n        trackEvent(event);\n    }\n\n    public class RemoveStickySubscriber {\n        @SuppressWarnings(\"unused\")\n        @Subscribe(sticky = true)\n        public void onEvent(String event) {\n            eventBus.removeStickyEvent(event);\n        }\n    }\n\n    public class NonStickySubscriber {\n        @Subscribe\n        public void onEvent(String event) {\n            trackEvent(event);\n        }\n\n        @Subscribe\n        public void onEvent(IntTestEvent event) {\n            trackEvent(event);\n        }\n    }\n\n    public class StickyIntTestSubscriber {\n        @Subscribe(sticky = true)\n        public void onEvent(IntTestEvent event) {\n            trackEvent(event);\n        }\n    }\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertSame;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusSubscriberExceptionTest extends AbstractEventBusTest {\n\n    @Test\n    public void testSubscriberExceptionEvent() {\n        eventBus = EventBus.builder().logSubscriberExceptions(false).build();\n        eventBus.register(this);\n        eventBus.post(\"Foo\");\n        assertEventCount(1);\n        assertEquals(SubscriberExceptionEvent.class, lastEvent.getClass());\n        SubscriberExceptionEvent exEvent = (SubscriberExceptionEvent) lastEvent;\n        assertEquals(\"Foo\", exEvent.causingEvent);\n        assertSame(this, exEvent.causingSubscriber);\n        assertEquals(\"Bar\", exEvent.throwable.getMessage());\n    }\n\n    @Test\n    public void testBadExceptionSubscriber() {\n        eventBus = EventBus.builder().logSubscriberExceptions(false).build();\n        eventBus.register(this);\n        eventBus.register(new BadExceptionSubscriber());\n        eventBus.post(\"Foo\");\n        assertEventCount(1);\n    }\n\n    @Subscribe\n    public void onEvent(String event) {\n        throw new RuntimeException(\"Bar\");\n    }\n\n    @Subscribe\n    public void onEvent(SubscriberExceptionEvent event) {\n        trackEvent(event);\n    }\n\n    public class BadExceptionSubscriber {\n        @Subscribe\n        public void onEvent(SubscriberExceptionEvent event) {\n            throw new RuntimeException(\"Bad\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage org.greenrobot.eventbus;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\npublic class EventBusSubscriberInJarTest {\n    protected EventBus eventBus = EventBus.builder().build();\n\n    @Test\n    public void testSubscriberInJar() {\n        SubscriberInJar subscriber = new SubscriberInJar();\n        eventBus.register(subscriber);\n        eventBus.post(\"Hi Jar\");\n        eventBus.post(42);\n        Assert.assertEquals(1, subscriber.getCollectedStrings().size());\n        Assert.assertEquals(\"Hi Jar\", subscriber.getCollectedStrings().get(0));\n    }\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author Markus Junginger, greenrobot\n */\npublic class EventBusSubscriberLegalTest extends AbstractEventBusTest {\n\n    @Test\n    public void testSubscriberLegal() {\n        eventBus.register(this);\n        eventBus.post(\"42\");\n        eventBus.unregister(this);\n        assertEquals(1, eventCount.intValue());\n    }\n\n    // With build time verification, some of these tests are obsolete (and cause problems during build)\n//    public void testSubscriberNotPublic() {\n//        try {\n//            eventBus.register(new NotPublic());\n//            fail(\"Registration of ilegal subscriber successful\");\n//        } catch (EventBusException e) {\n//            // Expected\n//        }\n//    }\n\n//    public void testSubscriberStatic() {\n//        try {\n//            eventBus.register(new Static());\n//            fail(\"Registration of ilegal subscriber successful\");\n//        } catch (EventBusException e) {\n//            // Expected\n//        }\n//    }\n\n    public void testSubscriberLegalAbstract() {\n        eventBus.register(new AbstractImpl());\n\n        eventBus.post(\"42\");\n        assertEquals(1, eventCount.intValue());\n    }\n\n    @Subscribe\n    public void onEvent(String event) {\n        trackEvent(event);\n    }\n\n//    public static class NotPublic {\n//        @Subscribe\n//        void onEvent(String event) {\n//        }\n//    }\n\n    public static abstract class Abstract {\n        @Subscribe\n        public abstract void onEvent(String event);\n    }\n\n    public class AbstractImpl extends Abstract {\n\n        @Override\n        @Subscribe\n        public void onEvent(String event) {\n            trackEvent(event);\n        }\n\n    }\n\n//    public static class Static {\n//        @Subscribe\n//        public static void onEvent(String event) {\n//        }\n//    }\n\n}\n"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/IntTestEvent.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Simple event storing an int value. More efficient than Integer because of the its flat hierarchy. \n */\npackage org.greenrobot.eventbus;\n\npublic class IntTestEvent {\n    public final int value;\n\n    public IntTestEvent(int value) {\n        this.value = value;\n    }\n\n}\n"
  },
  {
    "path": "EventBusTestSubscriberInJar/build.gradle",
    "content": "apply plugin: \"java-library\"\n\ngroup = \"de.greenrobot\"\nversion = \"3.0.0\"\njava.sourceCompatibility = JavaVersion.VERSION_1_8\njava.targetCompatibility = JavaVersion.VERSION_1_8\n\nconfigurations {\n    provided\n}\n\ndependencies {\n    implementation project(\":eventbus-java\")\n    annotationProcessor project(\":eventbus-annotation-processor\")\n}\n\nsourceSets {\n    main {\n        compileClasspath += configurations.provided\n        java {\n            srcDir \"src\"\n        }\n    }\n}\n\ncompileJava {\n    options.compilerArgs << \"-AeventBusIndex=org.greenrobot.eventbus.InJarIndex\"\n    options.fork = true\n}\n"
  },
  {
    "path": "EventBusTestSubscriberInJar/src/org/greenrobot/eventbus/SubscriberInJar.java",
    "content": "package org.greenrobot.eventbus;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Helper class used by test inside a jar. */\npublic class SubscriberInJar {\n    List<String> collectedStrings = new ArrayList<String>();\n\n    @Subscribe\n    public void collectString(String string) {\n        collectedStrings.add(string);\n    }\n\n    public List<String> getCollectedStrings() {\n        return collectedStrings;\n    }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "EventBus\n========\n[EventBus](https://greenrobot.org/eventbus/) is a publish/subscribe event bus for Android and Java.<br/>\n<img src=\"EventBus-Publish-Subscribe.png\" width=\"500\" height=\"187\"/>\n\n[![Build Status](https://github.com/greenrobot/EventBus/actions/workflows/gradle.yml/badge.svg)](https://github.com/greenrobot/EventBus/actions)\n[![Follow greenrobot on Twitter](https://img.shields.io/twitter/follow/greenrobot_de.svg?style=flat-square&logo=twitter)](https://twitter.com/greenrobot_de)\n\nEventBus...\n\n * simplifies the communication between components\n    * decouples event senders and receivers\n    * performs well with Activities, Fragments, and background threads\n    * avoids complex and error-prone dependencies and life cycle issues\n * makes your code simpler\n * is fast\n * is tiny (~60k jar)\n * is proven in practice by apps with 1,000,000,000+ installs\n * has advanced features like delivery threads, subscriber priorities, etc.\n\nEventBus in 3 steps\n-------------------\n1. Define events:\n\n    ```java  \n    public static class MessageEvent { /* Additional fields if needed */ }\n    ```\n\n2. Prepare subscribers:\n    Declare and annotate your subscribing method, optionally specify a [thread mode](https://greenrobot.org/eventbus/documentation/delivery-threads-threadmode/):  \n\n    ```java\n    @Subscribe(threadMode = ThreadMode.MAIN)  \n    public void onMessageEvent(MessageEvent event) {\n        // Do something\n    }\n    ```\n    Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:\n\n   ```java\n    @Override\n    public void onStart() {\n        super.onStart();\n        EventBus.getDefault().register(this);\n    }\n \n    @Override\n    public void onStop() {\n        super.onStop();\n        EventBus.getDefault().unregister(this);\n    }\n    ```\n\n3. Post events:\n\n   ```java\n    EventBus.getDefault().post(new MessageEvent());\n    ```\n\nRead the full [getting started guide](https://greenrobot.org/eventbus/documentation/how-to-get-started/).\n\nThere are also some [examples](https://github.com/greenrobot-team/greenrobot-examples).\n\n**Note:** we highly recommend the [EventBus annotation processor with its subscriber index](https://greenrobot.org/eventbus/documentation/subscriber-index/).\nThis will avoid some reflection related problems seen in the wild.  \n\nAdd EventBus to your project\n----------------------------\n<a href=\"https://search.maven.org/search?q=g:org.greenrobot%20AND%20a:eventbus\"><img src=\"https://img.shields.io/maven-central/v/org.greenrobot/eventbus.svg\"></a>\n\nAvailable on <a href=\"https://search.maven.org/search?q=g:org.greenrobot%20AND%20a:eventbus\">Maven Central</a>.\n\nAndroid projects:\n```groovy\nimplementation(\"org.greenrobot:eventbus:3.3.1\")\n```\n\nJava projects:\n```groovy\nimplementation(\"org.greenrobot:eventbus-java:3.3.1\")\n```\n```xml\n<dependency>\n    <groupId>org.greenrobot</groupId>\n    <artifactId>eventbus-java</artifactId>\n    <version>3.3.1</version>\n</dependency>\n```\n\nR8, ProGuard\n------------\n\nIf your project uses R8 or ProGuard this library ships [with embedded rules](/eventbus-android/consumer-rules.pro).\n\nHomepage, Documentation, Links\n------------------------------\nFor more details please check the [EventBus website](https://greenrobot.org/eventbus). Here are some direct links you may find useful:\n\n[Features](https://greenrobot.org/eventbus/features/)\n\n[Documentation](https://greenrobot.org/eventbus/documentation/)\n\n[Changelog](https://github.com/greenrobot/EventBus/releases)\n\n[FAQ](https://greenrobot.org/eventbus/documentation/faq/)\n\nLicense\n-------\nCopyright (C) 2012-2021 Markus Junginger, greenrobot (https://greenrobot.org)\n\nEventBus binaries and source code can be used according to the [Apache License, Version 2.0](LICENSE).\n\nOther projects by greenrobot\n============================\n[__ObjectBox__](https://objectbox.io/) ([GitHub](https://github.com/objectbox/objectbox-java)) is a new superfast object-oriented database.\n\n[__Essentials__](https://github.com/greenrobot/essentials) is a set of utility classes and hash functions for Android & Java projects.\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    ext {\n        _compileSdkVersion = 30 // Android 11 (R)\n    }\n    repositories {\n        mavenCentral()\n        maven { url \"https://plugins.gradle.org/m2/\" }\n    }\n    dependencies {\n        classpath \"io.github.gradle-nexus:publish-plugin:1.1.0\"\n    }\n}\n\n// Set group and version in root build.gradle so publish-plugin can detect them.\ngroup = \"org.greenrobot\"\nversion = \"3.3.1\"\n\nallprojects {\n    repositories {\n        mavenCentral()\n        google()\n    }\n}\n\nif (JavaVersion.current().isJava8Compatible()) {\n    allprojects {\n        tasks.withType(Javadoc) {\n            options.addStringOption('Xdoclint:none', '-quiet')\n        }\n    }\n}\n\nwrapper {\n    distributionType = Wrapper.DistributionType.ALL\n}\n\n// Plugin to publish to Central https://github.com/gradle-nexus/publish-plugin/\n// This plugin ensures a separate, named staging repo is created for each build when publishing.\napply plugin: \"io.github.gradle-nexus.publish-plugin\"\nnexusPublishing {\n    repositories {\n        sonatype {\n            if (project.hasProperty(\"sonatypeUsername\") && project.hasProperty(\"sonatypePassword\")) {\n                println('nexusPublishing credentials supplied.')\n                username = sonatypeUsername\n                password = sonatypePassword\n            } else {\n                println('nexusPublishing credentials NOT supplied.')\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "eventbus-android/.gitignore",
    "content": "/build"
  },
  {
    "path": "eventbus-android/README.md",
    "content": "# EventBus for Android\n\nDespite its name this module is actually published as `org.greenrobot:eventbus` as an Android library (AAR).\n\nIt has a dependency on the Java-only artifact `org.greenrobot:eventbus-java` (JAR) previously available under the `eventbus` name.\n\nProvides an `AndroidComponents` implementation to the Java library if it detects `AndroidComponentsImpl` on the classpath via reflection.\n"
  },
  {
    "path": "eventbus-android/build.gradle",
    "content": "buildscript {\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1\n        classpath 'com.android.tools.build:gradle:4.1.3'\n    }\n}\n\napply plugin: 'com.android.library'\n\ngroup = rootProject.group\nversion = rootProject.version\n\nandroid {\n    compileSdkVersion _compileSdkVersion\n\n    defaultConfig {\n        minSdkVersion 7\n        targetSdkVersion 30 // Android 11 (R)\n\n        consumerProguardFiles \"consumer-rules.pro\"\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n    api project(\":eventbus-java\")\n}\n\ntask sourcesJar(type: Jar) {\n    from android.sourceSets.main.java.srcDirs\n    archiveClassifier.set(\"sources\")\n}\n\napply from: rootProject.file(\"gradle/publish.gradle\")\n// Set project-specific properties\n// https://developer.android.com/studio/build/maven-publish-plugin\n// Because the Android components are created only during the afterEvaluate phase, you must\n// configure your publications using the afterEvaluate() lifecycle method.\nafterEvaluate {\n    publishing.publications {\n        mavenJava(MavenPublication) {\n            artifactId = \"eventbus\"\n\n            from components.release\n            artifact sourcesJar\n\n            pom {\n                name = \"EventBus\"\n                description = \"EventBus is a publish/subscribe event bus optimized for Android.\"\n                packaging = \"aar\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "eventbus-android/consumer-rules.pro",
    "content": "-keepattributes *Annotation*\n-keepclassmembers class * {\n    @org.greenrobot.eventbus.Subscribe <methods>;\n}\n-keep enum org.greenrobot.eventbus.ThreadMode { *; }\n\n# If using AsyncExecutord, keep required constructor of default event used.\n# Adjust the class name if a custom failure event type is used.\n-keepclassmembers class org.greenrobot.eventbus.util.ThrowableFailureEvent {\n    <init>(java.lang.Throwable);\n}\n\n# Accessed via reflection, avoid renaming or removal\n-keep class org.greenrobot.eventbus.android.AndroidComponentsImpl\n"
  },
  {
    "path": "eventbus-android/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile"
  },
  {
    "path": "eventbus-android/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"org.greenrobot.eventbus.android\">\n\n</manifest>"
  },
  {
    "path": "eventbus-android/src/main/java/org/greenrobot/eventbus/HandlerPoster.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.os.Message;\nimport android.os.SystemClock;\n\npublic class HandlerPoster extends Handler implements Poster {\n\n    private final PendingPostQueue queue;\n    private final int maxMillisInsideHandleMessage;\n    private final EventBus eventBus;\n    private boolean handlerActive;\n\n    public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {\n        super(looper);\n        this.eventBus = eventBus;\n        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;\n        queue = new PendingPostQueue();\n    }\n\n    public void enqueue(Subscription subscription, Object event) {\n        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);\n        synchronized (this) {\n            queue.enqueue(pendingPost);\n            if (!handlerActive) {\n                handlerActive = true;\n                if (!sendMessage(obtainMessage())) {\n                    throw new EventBusException(\"Could not send handler message\");\n                }\n            }\n        }\n    }\n\n    @Override\n    public void handleMessage(Message msg) {\n        boolean rescheduled = false;\n        try {\n            long started = SystemClock.uptimeMillis();\n            while (true) {\n                PendingPost pendingPost = queue.poll();\n                if (pendingPost == null) {\n                    synchronized (this) {\n                        // Check again, this time in synchronized\n                        pendingPost = queue.poll();\n                        if (pendingPost == null) {\n                            handlerActive = false;\n                            return;\n                        }\n                    }\n                }\n                eventBus.invokeSubscriber(pendingPost);\n                long timeInMethod = SystemClock.uptimeMillis() - started;\n                if (timeInMethod >= maxMillisInsideHandleMessage) {\n                    if (!sendMessage(obtainMessage())) {\n                        throw new EventBusException(\"Could not send handler message\");\n                    }\n                    rescheduled = true;\n                    return;\n                }\n            }\n        } finally {\n            handlerActive = rescheduled;\n        }\n    }\n}"
  },
  {
    "path": "eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java",
    "content": "package org.greenrobot.eventbus.android;\n\n/**\n * Used via reflection in the Java library by {@link AndroidDependenciesDetector}.\n */\npublic class AndroidComponentsImpl extends AndroidComponents {\n\n    public AndroidComponentsImpl() {\n        super(new AndroidLogger(\"EventBus\"), new DefaultAndroidMainThreadSupport());\n    }\n}\n"
  },
  {
    "path": "eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java",
    "content": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.greenrobot.eventbus.android;\n\nimport android.util.Log;\nimport org.greenrobot.eventbus.Logger;\n\nimport java.util.logging.Level;\n\npublic class AndroidLogger implements Logger {\n\n    private final String tag;\n\n    public AndroidLogger(String tag) {\n        this.tag = tag;\n    }\n\n    public void log(Level level, String msg) {\n        if (level != Level.OFF) {\n            Log.println(mapLevel(level), tag, msg);\n        }\n    }\n\n    public void log(Level level, String msg, Throwable th) {\n        if (level != Level.OFF) {\n            // That's how Log does it internally\n            Log.println(mapLevel(level), tag, msg + \"\\n\" + Log.getStackTraceString(th));\n        }\n    }\n\n    private int mapLevel(Level level) {\n        int value = level.intValue();\n        if (value < 800) { // below INFO\n            if (value < 500) { // below FINE\n                return Log.VERBOSE;\n            } else {\n                return Log.DEBUG;\n            }\n        } else if (value < 900) { // below WARNING\n            return Log.INFO;\n        } else if (value < 1000) { // below ERROR\n            return Log.WARN;\n        } else {\n            return Log.ERROR;\n        }\n    }\n}\n"
  },
  {
    "path": "eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java",
    "content": "package org.greenrobot.eventbus.android;\n\nimport android.os.Looper;\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.HandlerPoster;\nimport org.greenrobot.eventbus.MainThreadSupport;\nimport org.greenrobot.eventbus.Poster;\n\npublic class DefaultAndroidMainThreadSupport implements MainThreadSupport {\n\n    @Override\n    public boolean isMainThread() {\n        return Looper.getMainLooper() == Looper.myLooper();\n    }\n\n    @Override\n    public Poster createPoster(EventBus eventBus) {\n        return new HandlerPoster(eventBus, Looper.getMainLooper(), 10);\n    }\n}\n"
  },
  {
    "path": "gradle/publish.gradle",
    "content": "// Configures common publishing settings.\n\napply plugin: \"maven-publish\"\napply plugin: \"signing\"\n\npublishing {\n    publications {\n        // Note: Sonatype repo created by publish-plugin, see root build.gradle.\n        mavenJava(MavenPublication) {\n            pom {\n                url = \"https://greenrobot.org/eventbus/\"\n\n                scm {\n                    connection = \"scm:git@github.com:greenrobot/EventBus.git\"\n                    developerConnection = \"scm:git@github.com:greenrobot/EventBus.git\"\n                    url = \"https://github.com/greenrobot/EventBus\"\n                }\n\n                licenses {\n                    license {\n                        name = \"The Apache Software License, Version 2.0\"\n                        url = \"https://www.apache.org/licenses/LICENSE-2.0.txt\"\n                        distribution = \"repo\"\n                    }\n                }\n\n                developers {\n                    developer {\n                        id = \"greenrobot\"\n                        name = \"greenrobot\"\n                    }\n                }\n\n                issueManagement {\n                    system = \"https://github.com/greenrobot/EventBus/issues\"\n                    url = \"https://github.com/greenrobot/EventBus/issues\"\n                }\n\n                organization {\n                    name = \"greenrobot\"\n                    url = \"https://greenrobot.org\"\n                }\n            }\n        }\n    }\n}\n\n// Note: ext to export to scripts applying this script.\next {\n    // Signing: in-memory ascii-armored key (CI) or keyring file (dev machine), see https://docs.gradle.org/current/userguide/signing_plugin.html\n    hasSigningPropertiesKeyFile = {\n        return (project.hasProperty('signingKeyId')\n                && project.hasProperty('signingKeyFile')\n                && project.hasProperty('signingPassword'))\n    }\n    // Typically via ~/.gradle/gradle.properties; default properties for signing plugin.\n    hasSigningPropertiesKeyRing = {\n        return (project.hasProperty('signing.keyId')\n                && project.hasProperty('signing.secretKeyRingFile')\n                && project.hasProperty('signing.password'))\n    }\n    hasSigningProperties = {\n        return hasSigningPropertiesKeyFile() || hasSigningPropertiesKeyRing()\n    }\n}\n\nsigning {\n    if (hasSigningProperties()) {\n        if (hasSigningPropertiesKeyFile()) {\n            println \"Configured signing to use key file.\"\n            String signingKey = new File(signingKeyFile).text\n            useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)\n        } else if (hasSigningPropertiesKeyRing()) {\n            println \"Configured signing to use key ring.\"\n            // Note: using expected property names (see above), no need to configure anything.\n        }\n        sign publishing.publications.mavenJava\n    } else {\n        println \"WARNING: signing properties NOT set, will not sign artifacts.\"\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.8.3-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "javadoc-style/stylesheet.css",
    "content": "/* Javadoc style sheet */\n/*\nOverall document style\n*/\n\n@import url('resources/fonts/dejavu.css');\n\nbody {\n    background-color:#ffffff;\n    color:#353833;\n    font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;\n    font-size:14px;\n    margin:0;\n}\na:link, a:visited {\n    text-decoration:none;\n    color:#4A6782;\n}\na:hover, a:focus {\n    text-decoration:none;\n    color:#bb7a2a;\n}\na:active {\n    text-decoration:none;\n    color:#4A6782;\n}\na[name] {\n    color:#353833;\n}\na[name]:hover {\n    text-decoration:none;\n    color:#353833;\n}\npre {\n    font-family:'DejaVu Sans Mono', monospace;\n    font-size:14px;\n}\nh1 {\n    font-size:20px;\n}\nh2 {\n    font-size:18px;\n}\nh3 {\n    font-size:16px;\n    font-style:italic;\n}\nh4 {\n    font-size:13px;\n}\nh5 {\n    font-size:12px;\n}\nh6 {\n    font-size:11px;\n}\nul {\n    list-style-type:disc;\n}\ncode, tt {\n    font-family:'DejaVu Sans Mono', monospace;\n    font-size:14px;\n    padding-top:4px;\n    margin-top:8px;\n    line-height:1.4em;\n}\ndt code {\n    font-family:'DejaVu Sans Mono', monospace;\n    font-size:14px;\n    padding-top:4px;\n}\ntable tr td dt code {\n    font-family:'DejaVu Sans Mono', monospace;\n    font-size:14px;\n    vertical-align:top;\n    padding-top:4px;\n}\nsup {\n    font-size:8px;\n}\n/*\nDocument title and Copyright styles\n*/\n.clear {\n    clear:both;\n    height:0px;\n    overflow:hidden;\n}\n.aboutLanguage {\n    float:right;\n    padding:0px 21px;\n    font-size:11px;\n    z-index:200;\n    margin-top:-9px;\n}\n.legalCopy {\n    margin-left:.5em;\n}\n.bar a, .bar a:link, .bar a:visited, .bar a:active {\n    color:#FFFFFF;\n    text-decoration:none;\n}\n.bar a:hover, .bar a:focus {\n    color:#bb7a2a;\n}\n.tab {\n    background-color:#0066FF;\n    color:#ffffff;\n    padding:8px;\n    width:5em;\n    font-weight:bold;\n}\n/*\nNavigation bar styles\n*/\n.bar {\n    background-color:#4D974D;\n    color:#FFFFFF;\n    padding:.8em .5em .4em .8em;\n    height:auto;/*height:1.8em;*/\n    font-size:11px;\n    margin:0;\n}\n.topNav {\n    background-color:#4D974D;\n    color:#FFFFFF;\n    float:left;\n    padding:0;\n    width:100%;\n    clear:right;\n    height:2.8em;\n    padding-top:10px;\n    overflow:hidden;\n    font-size:12px; \n}\n.bottomNav {\n    margin-top:10px;\n    background-color:#4D974D;\n    color:#FFFFFF;\n    float:left;\n    padding:0;\n    width:100%;\n    clear:right;\n    height:2.8em;\n    padding-top:10px;\n    overflow:hidden;\n    font-size:12px;\n}\n.subNav {\n    background-color:#dee3e9;\n    float:left;\n    width:100%;\n    overflow:hidden;\n    font-size:12px;\n}\n.subNav div {\n    clear:left;\n    float:left;\n    padding:0 0 5px 6px;\n    text-transform:uppercase;\n}\nul.navList, ul.subNavList {\n    float:left;\n    margin:0 25px 0 0;\n    padding:0;\n}\nul.navList li{\n    list-style:none;\n    float:left;\n    padding: 5px 6px;\n    text-transform:uppercase;\n}\nul.subNavList li{\n    list-style:none;\n    float:left;\n}\n.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {\n    color:#FFFFFF;\n    text-decoration:none;\n    text-transform:uppercase;\n}\n.topNav a:hover, .bottomNav a:hover {\n    text-decoration:none;\n    color:#bb7a2a;\n    text-transform:uppercase;\n}\n.navBarCell1Rev {\n    background-color:#F8981D;\n    color:#253441;\n    margin: auto 5px;\n}\n.skipNav {\n    position:absolute;\n    top:auto;\n    left:-9999px;\n    overflow:hidden;\n}\n/*\nPage header and footer styles\n*/\n.header, .footer {\n    clear:both;\n    margin:0 20px;\n    padding:5px 0 0 0;\n}\n.indexHeader {\n    margin:10px;\n    position:relative;\n}\n.indexHeader span{\n    margin-right:15px;\n}\n.indexHeader h1 {\n    font-size:13px;\n}\n.title {\n    color:#2c4557;\n    margin:10px 0;\n}\n.subTitle {\n    margin:5px 0 0 0;\n}\n.header ul {\n    margin:0 0 15px 0;\n    padding:0;\n}\n.footer ul {\n    margin:20px 0 5px 0;\n}\n.header ul li, .footer ul li {\n    list-style:none;\n    font-size:13px;\n}\n/*\nHeading styles\n*/\ndiv.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {\n    background-color:#dee3e9;\n    border:1px solid #d0d9e0;\n    margin:0 0 6px -8px;\n    padding:7px 5px;\n}\nul.blockList ul.blockList ul.blockList li.blockList h3 {\n    background-color:#dee3e9;\n    border:1px solid #d0d9e0;\n    margin:0 0 6px -8px;\n    padding:7px 5px;\n}\nul.blockList ul.blockList li.blockList h3 {\n    padding:0;\n    margin:15px 0;\n}\nul.blockList li.blockList h2 {\n    padding:0px 0 20px 0;\n}\n/*\nPage layout container styles\n*/\n.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {\n    clear:both;\n    padding:10px 20px;\n    position:relative;\n}\n.indexContainer {\n    margin:10px;\n    position:relative;\n    font-size:12px;\n}\n.indexContainer h2 {\n    font-size:13px;\n    padding:0 0 3px 0;\n}\n.indexContainer ul {\n    margin:0;\n    padding:0;\n}\n.indexContainer ul li {\n    list-style:none;\n    padding-top:2px;\n}\n.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {\n    font-size:12px;\n    font-weight:bold;\n    margin:10px 0 0 0;\n    color:#4E4E4E;\n}\n.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {\n    margin:5px 0 10px 0px;\n    font-size:14px;\n    font-family:'DejaVu Sans Mono',monospace;\n}\n.serializedFormContainer dl.nameValue dt {\n    margin-left:1px;\n    font-size:1.1em;\n    display:inline;\n    font-weight:bold;\n}\n.serializedFormContainer dl.nameValue dd {\n    margin:0 0 0 1px;\n    font-size:1.1em;\n    display:inline;\n}\n/*\nList styles\n*/\nul.horizontal li {\n    display:inline;\n    font-size:0.9em;\n}\nul.inheritance {\n    margin:0;\n    padding:0;\n}\nul.inheritance li {\n    display:inline;\n    list-style:none;\n}\nul.inheritance li ul.inheritance {\n    margin-left:15px;\n    padding-left:15px;\n    padding-top:1px;\n}\nul.blockList, ul.blockListLast {\n    margin:10px 0 10px 0;\n    padding:0;\n}\nul.blockList li.blockList, ul.blockListLast li.blockList {\n    list-style:none;\n    margin-bottom:15px;\n    line-height:1.4;\n}\nul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {\n    padding:0px 20px 5px 10px;\n    border:1px solid #ededed; \n    background-color:#f8f8f8;\n}\nul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {\n    padding:0 0 5px 8px;\n    background-color:#ffffff;\n    border:none;\n}\nul.blockList ul.blockList ul.blockList ul.blockList li.blockList {\n    margin-left:0;\n    padding-left:0;\n    padding-bottom:15px;\n    border:none;\n}\nul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {\n    list-style:none;\n    border-bottom:none;\n    padding-bottom:0;\n}\ntable tr td dl, table tr td dl dt, table tr td dl dd {\n    margin-top:0;\n    margin-bottom:1px;\n}\n/*\nTable styles\n*/\n.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {\n    width:100%;\n    border-left:1px solid #EEE; \n    border-right:1px solid #EEE; \n    border-bottom:1px solid #EEE; \n}\n.overviewSummary, .memberSummary  {\n    padding:0px;\n}\n.overviewSummary caption, .memberSummary caption, .typeSummary caption,\n.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {\n    position:relative;\n    text-align:left;\n    background-repeat:no-repeat;\n    color:#253441;\n    font-weight:bold;\n    clear:none;\n    overflow:hidden;\n    padding:0px;\n    padding-top:10px;\n    padding-left:1px;\n    margin:0px;\n    white-space:pre;\n}\n.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,\n.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,\n.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,\n.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,\n.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,\n.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,\n.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,\n.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {\n    color:#FFFFFF;\n}\n.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,\n.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {\n    white-space:nowrap;\n    padding-top:5px;\n    padding-left:12px;\n    padding-right:12px;\n    padding-bottom:7px;\n    display:inline-block;\n    float:left;\n    background-color:#F8981D;\n    border: none;\n    height:16px;\n}\n.memberSummary caption span.activeTableTab span {\n    white-space:nowrap;\n    padding-top:5px;\n    padding-left:12px;\n    padding-right:12px;\n    margin-right:3px;\n    display:inline-block;\n    float:left;\n    background-color:#F8981D;\n    height:16px;\n}\n.memberSummary caption span.tableTab span {\n    white-space:nowrap;\n    padding-top:5px;\n    padding-left:12px;\n    padding-right:12px;\n    margin-right:3px;\n    display:inline-block;\n    float:left;\n    background-color:#4D974D;\n    height:16px;\n}\n.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab {\n    padding-top:0px;\n    padding-left:0px;\n    padding-right:0px;\n    background-image:none;\n    float:none;\n    display:inline;\n}\n.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,\n.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {\n    display:none;\n    width:5px;\n    position:relative;\n    float:left;\n    background-color:#F8981D;\n}\n.memberSummary .activeTableTab .tabEnd {\n    display:none;\n    width:5px;\n    margin-right:3px;\n    position:relative; \n    float:left;\n    background-color:#F8981D;\n}\n.memberSummary .tableTab .tabEnd {\n    display:none;\n    width:5px;\n    margin-right:3px;\n    position:relative;\n    background-color:#4D974D;\n    float:left;\n\n}\n.overviewSummary td, .memberSummary td, .typeSummary td,\n.useSummary td, .constantsSummary td, .deprecatedSummary td {\n    text-align:left;\n    padding:0px 0px 12px 10px;\n    width:100%;\n}\nth.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,\ntd.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{\n    vertical-align:top;\n    padding-right:0px;\n    padding-top:8px;\n    padding-bottom:3px;\n}\nth.colFirst, th.colLast, th.colOne, .constantsSummary th {\n    background:#dee3e9;\n    text-align:left;\n    padding:8px 3px 3px 7px;\n}\ntd.colFirst, th.colFirst {\n    white-space:nowrap;\n    font-size:13px;\n}\ntd.colLast, th.colLast {\n    font-size:13px;\n}\ntd.colOne, th.colOne {\n    font-size:13px;\n}\n.overviewSummary td.colFirst, .overviewSummary th.colFirst,\n.overviewSummary td.colOne, .overviewSummary th.colOne,\n.memberSummary td.colFirst, .memberSummary th.colFirst,\n.memberSummary td.colOne, .memberSummary th.colOne,\n.typeSummary td.colFirst{\n    width:25%;\n    vertical-align:top;\n}\ntd.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {\n    font-weight:bold;\n}\n.tableSubHeadingColor {\n    background-color:#EEEEFF;\n}\n.altColor {\n    background-color:#FFFFFF;\n}\n.rowColor {\n    background-color:#EEEEEF;\n}\n/*\nContent styles\n*/\n.description pre {\n    margin-top:0;\n}\n.deprecatedContent {\n    margin:0;\n    padding:10px 0;\n}\n.docSummary {\n    padding:0;\n}\n\nul.blockList ul.blockList ul.blockList li.blockList h3 {\n    font-style:normal;\n}\n\ndiv.block {\n    font-size:14px;\n    font-family:'DejaVu Serif', Georgia, \"Times New Roman\", Times, serif;\n}\n\ntd.colLast div {\n    padding-top:0px;\n}\n\n\ntd.colLast a {\n    padding-bottom:3px;\n}\n/*\nFormatting effect styles\n*/\n.sourceLineNo {\n    color:green;\n    padding:0 30px 0 0;\n}\nh1.hidden {\n    visibility:hidden;\n    overflow:hidden;\n    font-size:10px;\n}\n.block {\n    display:block;\n    margin:3px 10px 2px 0px;\n    color:#474747;\n}\n.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,\n.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,\n.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink {\n    font-weight:bold;\n}\n.deprecationComment, .emphasizedPhrase, .interfaceName {\n    font-style:italic;\n}\n\ndiv.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase,\ndiv.block div.block span.interfaceName {\n    font-style:normal;\n}\n\ndiv.contentContainer ul.blockList li.blockList h2{\n    padding-bottom:0px;\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':EventBus'\ninclude ':EventBusAnnotationProcessor'\ninclude ':EventBusTestJava'\ninclude ':EventBusTest'\ninclude ':EventBusTestSubscriberInJar'\ninclude ':EventBusPerformance'\ninclude ':eventbus-android'\n\nproject(\":EventBus\").name = \"eventbus-java\"\nproject(\":EventBusAnnotationProcessor\").name = \"eventbus-annotation-processor\"\n"
  }
]