Full Code of greenrobot/EventBus for AI

master 0194926b3bcf cached
134 files
333.0 KB
76.9k tokens
735 symbols
1 requests
Download .txt
Showing preview only (372K chars total). Download the full file or copy to clipboard to get everything.
Repository: greenrobot/EventBus
Branch: master
Commit: 0194926b3bcf
Files: 134
Total size: 333.0 KB

Directory structure:
gitextract_vwo4kya5/

├── .github/
│   └── workflows/
│       └── gradle.yml
├── .gitignore
├── COMPARISON.md
├── CONTRIBUTING.md
├── EventBus/
│   ├── build.gradle
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   ├── AsyncPoster.java
│                   ├── BackgroundPoster.java
│                   ├── EventBus.java
│                   ├── EventBusBuilder.java
│                   ├── EventBusException.java
│                   ├── Logger.java
│                   ├── MainThreadSupport.java
│                   ├── NoSubscriberEvent.java
│                   ├── PendingPost.java
│                   ├── PendingPostQueue.java
│                   ├── Poster.java
│                   ├── Subscribe.java
│                   ├── SubscriberExceptionEvent.java
│                   ├── SubscriberMethod.java
│                   ├── SubscriberMethodFinder.java
│                   ├── Subscription.java
│                   ├── ThreadMode.java
│                   ├── android/
│                   │   ├── AndroidComponents.java
│                   │   └── AndroidDependenciesDetector.java
│                   ├── meta/
│                   │   ├── AbstractSubscriberInfo.java
│                   │   ├── SimpleSubscriberInfo.java
│                   │   ├── SubscriberInfo.java
│                   │   ├── SubscriberInfoIndex.java
│                   │   └── SubscriberMethodInfo.java
│                   └── util/
│                       ├── AsyncExecutor.java
│                       ├── ExceptionToResourceMapping.java
│                       ├── HasExecutionScope.java
│                       └── ThrowableFailureEvent.java
├── EventBusAnnotationProcessor/
│   ├── build.gradle
│   ├── res/
│   │   └── META-INF/
│   │       └── services/
│   │           └── javax.annotation.processing.Processor
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   └── annotationprocessor/
│                       └── EventBusAnnotationProcessor.java
├── EventBusPerformance/
│   ├── .gitignore
│   ├── AndroidManifest.xml
│   ├── build.gradle
│   ├── proguard-project.txt
│   ├── project.properties
│   ├── res/
│   │   ├── layout/
│   │   │   ├── activity_runtests.xml
│   │   │   └── activity_setuptests.xml
│   │   └── values/
│   │       └── strings.xml
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbusperf/
│                   ├── Test.java
│                   ├── TestEvent.java
│                   ├── TestFinishedEvent.java
│                   ├── TestParams.java
│                   ├── TestRunner.java
│                   ├── TestRunnerActivity.java
│                   ├── TestSetupActivity.java
│                   └── testsubject/
│                       ├── PerfTestEventBus.java
│                       ├── PerfTestOtto.java
│                       └── SubscribeClassEventBusDefault.java
├── EventBusTest/
│   ├── AndroidManifest.xml
│   ├── build.gradle
│   ├── libs/
│   │   └── EventBusTestSubscriberInJar-3.0.0.jar
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   ├── AbstractAndroidEventBusTest.java
│                   ├── AndroidComponentsAvailabilityTest.java
│                   ├── ClassMapPerfTest.java
│                   ├── EventBusAndroidActivityTest.java
│                   ├── EventBusAndroidCancelEventDeliveryTest.java
│                   ├── EventBusAndroidMultithreadedTest.java
│                   ├── EventBusAndroidOrderTest.java
│                   ├── EventBusBackgroundThreadTest.java
│                   ├── EventBusMainThreadRacingTest.java
│                   ├── EventBusMainThreadTest.java
│                   ├── EventBusMethodModifiersTest.java
│                   ├── TestBackgroundPoster.java
│                   └── indexed/
│                       ├── EventBusAndroidOrderTestWithIndex.java
│                       ├── EventBusBackgroundThreadTestWithIndex.java
│                       ├── EventBusBasicTestWithIndex.java
│                       ├── EventBusCancelEventDeliveryTestWithIndex.java
│                       ├── EventBusFallbackToReflectionTestWithIndex.java
│                       ├── EventBusGenericsTestWithIndex.java
│                       ├── EventBusInheritanceDisabledTestWithIndex.java
│                       ├── EventBusInheritanceTestWithIndex.java
│                       ├── EventBusMainThreadRacingTestWithIndex.java
│                       ├── EventBusMainThreadTestWithIndex.java
│                       ├── EventBusMethodModifiersTestWithIndex.java
│                       ├── EventBusMultithreadedTestWithIndex.java
│                       ├── EventBusNoSubscriberEventTestWithIndex.java
│                       ├── EventBusOrderedSubscriptionsTestWithIndex.java
│                       ├── EventBusRegistrationRacingTestWithIndex.java
│                       ├── EventBusStickyEventTestWithIndex.java
│                       ├── EventBusSubscriberExceptionTestWithIndex.java
│                       ├── EventBusSubscriberInJarTestWithIndex.java
│                       └── Indexed.java
├── EventBusTestJava/
│   ├── build.gradle
│   ├── libs/
│   │   └── EventBusTestSubscriberInJar-3.0.0.jar
│   └── src/
│       └── main/
│           └── java/
│               └── org/
│                   └── greenrobot/
│                       └── eventbus/
│                           ├── AbstractEventBusTest.java
│                           ├── EventBusBasicTest.java
│                           ├── EventBusBuilderTest.java
│                           ├── EventBusCancelEventDeliveryTest.java
│                           ├── EventBusFallbackToReflectionTest.java
│                           ├── EventBusGenericsTest.java
│                           ├── EventBusIndexTest.java
│                           ├── EventBusInheritanceDisabledSubclassNoMethod.java
│                           ├── EventBusInheritanceDisabledSubclassTest.java
│                           ├── EventBusInheritanceDisabledTest.java
│                           ├── EventBusInheritanceSubclassNoMethodTest.java
│                           ├── EventBusInheritanceSubclassTest.java
│                           ├── EventBusInheritanceTest.java
│                           ├── EventBusMultithreadedTest.java
│                           ├── EventBusNoSubscriberEventTest.java
│                           ├── EventBusOrderedSubscriptionsTest.java
│                           ├── EventBusRegistrationRacingTest.java
│                           ├── EventBusStickyEventTest.java
│                           ├── EventBusSubscriberExceptionTest.java
│                           ├── EventBusSubscriberInJarTest.java
│                           ├── EventBusSubscriberLegalTest.java
│                           └── IntTestEvent.java
├── EventBusTestSubscriberInJar/
│   ├── build.gradle
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   └── SubscriberInJar.java
├── LICENSE
├── README.md
├── build.gradle
├── eventbus-android/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── org/
│                   └── greenrobot/
│                       └── eventbus/
│                           ├── HandlerPoster.java
│                           └── android/
│                               ├── AndroidComponentsImpl.java
│                               ├── AndroidLogger.java
│                               └── DefaultAndroidMainThreadSupport.java
├── gradle/
│   ├── publish.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── javadoc-style/
│   └── stylesheet.css
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/gradle.yml
================================================
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle

name: Java CI with Gradle

on:
  push:
  pull_request:

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'temurin'
          cache: gradle
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
      - name: Gradle Info
        run: ./gradlew -version
      - name: Build with Gradle
        run: ./gradlew build


================================================
FILE: .gitignore
================================================
# Built application files
*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
release/

# Gradle files
.gradle/
build/
gradle.properties

# Local configuration file (sdk path, etc)
local.properties

# IntelliJ project files
*.iml
.idea/

# Eclipse project files
.settings/

# Misc
.DS_Store


================================================
FILE: COMPARISON.md
================================================
EventBus Comparison
===================

Comparison with Square's Otto
-----------------------------
Otto 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:
<table>
    <tr>
        <th></th>
        <th>EventBus</th>
        <th>Otto</th>
    </tr>
    <tr>
        <th>Declare event handling methods</th>
        <td>Annotations (since 3.0, can be precompiled for best performance)</td>
        <td>Annotations</td>
    </tr>
    <tr>
        <th>Event inheritance</th>
        <td>Yes</td>
        <td>Yes</td>
    </tr>
    <tr>
        <th>Subscriber inheritance</th>
        <td>Yes</td>
        <td>No</td>
    </tr>
    <tr>
        <th>Cache most recent events</th>
        <td>Yes, sticky events</td>
        <td>No</td>
    </tr>
    <tr>
        <th>Event producers (e.g. for coding cached events)</th>
        <td>No</td>
        <td>Yes</td>
    </tr>
    <tr>
        <th>Event delivery in posting thread</th>
        <td>Yes (Default)</td>
        <td>Yes</td>
    </tr>
    <tr>
        <th>Event delivery in main thread</th>
        <td>Yes</td>
        <td>No</td>
    </tr>
    <tr>
        <th>Event delivery in background thread</th>
        <td>Yes</td>
        <td>No</td>
    </tr>
    <tr>
        <th>Asynchronous event delivery</th>
        <td>Yes</td>
        <td>No</td>
    </tr>
</table>

_**Note:** the following information is outdated, preprocessed annotations are much faster than EventBus 2.x, on which the following table is based._

Besides 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.

TODO: Update for EventBus 3 with and without index.

Benchmark results indicate that EventBus is significantly faster in almost every scenario:
<table>
    <tr>
        <th></th>
        <th>EventBus</th>
        <th>Otto</th>
    </tr>
    <tr>
        <th>Posting 1000 events, Android 2.3 emulator</th>
        <td>~70% faster</td>
        <td></td>
    </tr>
	<tr>
        <th>Posting 1000 events, S3 Android 4.0</th>
        <td>~110% faster</td>
        <td></td>
    </tr>
    <tr>
        <th>Register 1000 subscribers, Android 2.3 emulator</th>
        <td>~10% faster</td>
        <td></td>
    </tr>
    <tr>
        <th>Register 1000 subscribers, S3 Android 4.0</th>
        <td>~70% faster</td>
        <td></td>
    </tr>
    <tr>
        <th>Register subscribers cold start, Android 2.3 emulator</th>
        <td>~350% faster</td>
        <td></td>
    </tr>	
    <tr>
        <th>Register subscribers cold start, S3 Android 4.0</th>
        <td colspan="2">About the same</td>
    </tr>	
</table>


================================================
FILE: CONTRIBUTING.md
================================================
Before you create an Issue...
=============================

There are better Places for Support
-----------------------------------
We 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).
Instead, 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.

If you want professional support, check http://greenrobot.org/contact-support/.

Examples for support questions that are more likely to be answered on StackOverflow:

* Asking how something works
* Asking how to use EventBus in a specific scenario
* Your app crashes/misbehaves and you are not sure why

The perfect Issue Report
------------------------
A couple of simple steps can save time for everyone.

Check before reporting:

* It's not a support inquiry
* You have read the docs
* You searched the web and stackoverflow
* You searched existing issues to avoid duplicates

Reporting bugs:

 * Please investigate if is the bug is really caused by the library. Isolate the issue: what's the minimal code to reproduce the bug?
 * 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.

Requesting features:

 * 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.

A Note on Pull Requests
=======================
Pull requests (and issues) may queue up up a bit. Usually, pull requests and issues are checked when new releases are planned.

For bigger pull requests, it's a good idea to check with the maintainer upfront about the idea and the implementation outline.

Thanks for reading!
===================
It's your contributions and feedback that makes maintaining this library fun.


================================================
FILE: EventBus/build.gradle
================================================
apply plugin: 'java'

group = rootProject.group
version = rootProject.version

java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8

sourceSets {
    main {
        java {
            srcDir 'src'
            // exclude 'de/greenrobot/event/util/**'
        }
    }
}

javadoc {
    failOnError = false
    title = "EventBus ${version} API"
	options.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>'
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    archiveClassifier.set("javadoc")
    from 'build/docs/javadoc'
}

task sourcesJar(type: Jar) {
    archiveClassifier.set("sources")
    from sourceSets.main.allSource
}

apply from: rootProject.file("gradle/publish.gradle")
// Set project-specific properties
afterEvaluate {
    publishing.publications {
        mavenJava(MavenPublication) {
            artifactId = "eventbus-java"

            from components.java
            artifact javadocJar
            artifact sourcesJar
            pom {
                name = "EventBus"
                description = "EventBus is a publish/subscribe event bus."
                packaging = "jar"
            }
        }
    }
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/AsyncPoster.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;


/**
 * Posts events in background.
 * 
 * @author Markus
 */
class AsyncPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        eventBus.getExecutorService().execute(this);
    }

    @Override
    public void run() {
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import java.util.logging.Level;

/**
 * Posts events in background.
 *
 * @author Markus
 */
final class BackgroundPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    private volatile boolean executorRunning;

    BackgroundPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }

    @Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000);
                    if (pendingPost == null) {
                        synchronized (this) {
                            // Check again, this time in synchronized
                            pendingPost = queue.poll();
                            if (pendingPost == null) {
                                executorRunning = false;
                                return;
                            }
                        }
                    }
                    eventBus.invokeSubscriber(pendingPost);
                }
            } catch (InterruptedException e) {
                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interrupted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/EventBus.java
================================================
/*
 * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import org.greenrobot.eventbus.android.AndroidDependenciesDetector;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;

/**
 * EventBus is a central publish/subscribe event system for Java and Android.
 * Events are posted ({@link #post(Object)}) to the bus, which delivers it to subscribers that have a matching handler
 * method for the event type.
 * To receive events, subscribers must register themselves to the bus using {@link #register(Object)}.
 * Once registered, subscribers receive events until {@link #unregister(Object)} is called.
 * Event handling methods must be annotated by {@link Subscribe}, must be public, return nothing (void),
 * and have exactly one parameter (the event).
 *
 * @author Markus Junginger, greenrobot
 */
public class EventBus {

    /** Log tag, apps may override it. */
    public static String TAG = "EventBus";

    static volatile EventBus defaultInstance;

    private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
    private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();

    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    private final Map<Object, List<Class<?>>> typesBySubscriber;
    private final Map<Class<?>, Object> stickyEvents;

    private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };

    // @Nullable
    private final MainThreadSupport mainThreadSupport;
    // @Nullable
    private final Poster mainThreadPoster;
    private final BackgroundPoster backgroundPoster;
    private final AsyncPoster asyncPoster;
    private final SubscriberMethodFinder subscriberMethodFinder;
    private final ExecutorService executorService;

    private final boolean throwSubscriberException;
    private final boolean logSubscriberExceptions;
    private final boolean logNoSubscriberMessages;
    private final boolean sendSubscriberExceptionEvent;
    private final boolean sendNoSubscriberEvent;
    private final boolean eventInheritance;

    private final int indexCount;
    private final Logger logger;

    /** Convenience singleton for apps using a process-wide EventBus instance. */
    public static EventBus getDefault() {
        EventBus instance = defaultInstance;
        if (instance == null) {
            synchronized (EventBus.class) {
                instance = EventBus.defaultInstance;
                if (instance == null) {
                    instance = EventBus.defaultInstance = new EventBus();
                }
            }
        }
        return instance;
    }

    public static EventBusBuilder builder() {
        return new EventBusBuilder();
    }

    /** For unit test primarily. */
    public static void clearCaches() {
        SubscriberMethodFinder.clearCaches();
        eventTypesCache.clear();
    }

    /**
     * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a
     * central bus, consider {@link #getDefault()}.
     */
    public EventBus() {
        this(DEFAULT_BUILDER);
    }

    EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        mainThreadSupport = builder.getMainThreadSupport();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                builder.strictMethodVerification, builder.ignoreGeneratedIndex);
        logSubscriberExceptions = builder.logSubscriberExceptions;
        logNoSubscriberMessages = builder.logNoSubscriberMessages;
        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;
    }

    /**
     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
     * are no longer interested in receiving events.
     * <p/>
     * Subscribers have event handling methods that must be annotated by {@link Subscribe}.
     * The {@link Subscribe} annotation also allows configuration like {@link
     * ThreadMode} and priority.
     */
    public void register(Object subscriber) {
        if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) {
            // Crash if the user (developer) has not imported the Android compatibility library.
            throw new RuntimeException("It looks like you are using EventBus on Android, " +
                    "make sure to add the \"eventbus\" Android library to your dependencies.");
        }

        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

    // Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }

        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

        if (subscriberMethod.sticky) {
            if (eventInheritance) {
                // Existing sticky events of all subclasses of eventType have to be considered.
                // Note: Iterating over all events may be inefficient with lots of sticky events,
                // thus data structure should be changed to allow a more efficient lookup
                // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry<Class<?>, Object> entry : entries) {
                    Class<?> candidateEventType = entry.getKey();
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

    private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
        if (stickyEvent != null) {
            // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
            // --> Strange corner case, which we don't take care of here.
            postToSubscription(newSubscription, stickyEvent, isMainThread());
        }
    }

    /**
     * Checks if the current thread is running in the main thread.
     * If there is no main thread support (e.g. non-Android), "true" is always returned. In that case MAIN thread
     * subscribers are always called in posting thread, and BACKGROUND subscribers are always called from a background
     * poster.
     */
    private boolean isMainThread() {
        return mainThreadSupport == null || mainThreadSupport.isMainThread();
    }

    public synchronized boolean isRegistered(Object subscriber) {
        return typesBySubscriber.containsKey(subscriber);
    }

    /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
        List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

    /** Unregisters the given subscriber from all event classes. */
    public synchronized void unregister(Object subscriber) {
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

    /** Posts the given event to the event bus. */
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

    /**
     * Called from a subscriber's event handling method, further event delivery will be canceled. Subsequent
     * subscribers
     * won't receive the event. Events are usually canceled by higher priority subscribers (see
     * {@link Subscribe#priority()}). Canceling is restricted to event handling methods running in posting thread
     * {@link ThreadMode#POSTING}.
     */
    public void cancelEventDelivery(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        if (!postingState.isPosting) {
            throw new EventBusException(
                    "This method may only be called from inside event handling methods on the posting thread");
        } else if (event == null) {
            throw new EventBusException("Event may not be null");
        } else if (postingState.event != event) {
            throw new EventBusException("Only the currently handled event may be aborted");
        } else if (postingState.subscription.subscriberMethod.threadMode != ThreadMode.POSTING) {
            throw new EventBusException(" event handlers may only abort the incoming event");
        }

        postingState.canceled = true;
    }

    /**
     * Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky
     * event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.
     */
    public void postSticky(Object event) {
        synchronized (stickyEvents) {
            stickyEvents.put(event.getClass(), event);
        }
        // Should be posted after it is putted, in case the subscriber wants to remove immediately
        post(event);
    }

    /**
     * Gets the most recent sticky event for the given type.
     *
     * @see #postSticky(Object)
     */
    public <T> T getStickyEvent(Class<T> eventType) {
        synchronized (stickyEvents) {
            return eventType.cast(stickyEvents.get(eventType));
        }
    }

    /**
     * Remove and gets the recent sticky event for the given event type.
     *
     * @see #postSticky(Object)
     */
    public <T> T removeStickyEvent(Class<T> eventType) {
        synchronized (stickyEvents) {
            return eventType.cast(stickyEvents.remove(eventType));
        }
    }

    /**
     * Removes the sticky event if it equals to the given event.
     *
     * @return true if the events matched and the sticky event was removed.
     */
    public boolean removeStickyEvent(Object event) {
        synchronized (stickyEvents) {
            Class<?> eventType = event.getClass();
            Object existingEvent = stickyEvents.get(eventType);
            if (event.equals(existingEvent)) {
                stickyEvents.remove(eventType);
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * Removes all sticky events.
     */
    public void removeAllStickyEvents() {
        synchronized (stickyEvents) {
            stickyEvents.clear();
        }
    }

    public boolean hasSubscriberForEvent(Class<?> eventClass) {
        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
        if (eventTypes != null) {
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                CopyOnWriteArrayList<Subscription> subscriptions;
                synchronized (this) {
                    subscriptions = subscriptionsByEventType.get(clazz);
                }
                if (subscriptions != null && !subscriptions.isEmpty()) {
                    return true;
                }
            }
        }
        return false;
    }

    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        if (!subscriptionFound) {
            if (logNoSubscriberMessages) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted;
                try {
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }

    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING:
                invokeSubscriber(subscription, event);
                break;
            case MAIN:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(subscription, event);
                }
                break;
            case BACKGROUND:
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC:
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }

    /** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
    private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
        synchronized (eventTypesCache) {
            List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
            if (eventTypes == null) {
                eventTypes = new ArrayList<>();
                Class<?> clazz = eventClass;
                while (clazz != null) {
                    eventTypes.add(clazz);
                    addInterfaces(eventTypes, clazz.getInterfaces());
                    clazz = clazz.getSuperclass();
                }
                eventTypesCache.put(eventClass, eventTypes);
            }
            return eventTypes;
        }
    }

    /** Recurses through super interfaces. */
    static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
        for (Class<?> interfaceClass : interfaces) {
            if (!eventTypes.contains(interfaceClass)) {
                eventTypes.add(interfaceClass);
                addInterfaces(eventTypes, interfaceClass.getInterfaces());
            }
        }
    }

    /**
     * Invokes the subscriber if the subscriptions is still active. Skipping subscriptions prevents race conditions
     * between {@link #unregister(Object)} and event delivery. Otherwise the event might be delivered after the
     * subscriber unregistered. This is particularly important for main thread delivery and registrations bound to the
     * live cycle of an Activity or Fragment.
     */
    void invokeSubscriber(PendingPost pendingPost) {
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        PendingPost.releasePendingPost(pendingPost);
        if (subscription.active) {
            invokeSubscriber(subscription, event);
        }
    }

    void invokeSubscriber(Subscription subscription, Object event) {
        try {
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }

    private void handleSubscriberException(Subscription subscription, Object event, Throwable cause) {
        if (event instanceof SubscriberExceptionEvent) {
            if (logSubscriberExceptions) {
                // Don't send another SubscriberExceptionEvent to avoid infinite event recursion, just log
                logger.log(Level.SEVERE, "SubscriberExceptionEvent subscriber " + subscription.subscriber.getClass()
                        + " threw an exception", cause);
                SubscriberExceptionEvent exEvent = (SubscriberExceptionEvent) event;
                logger.log(Level.SEVERE, "Initial event " + exEvent.causingEvent + " caused exception in "
                        + exEvent.causingSubscriber, exEvent.throwable);
            }
        } else {
            if (throwSubscriberException) {
                throw new EventBusException("Invoking subscriber failed", cause);
            }
            if (logSubscriberExceptions) {
                logger.log(Level.SEVERE, "Could not dispatch event: " + event.getClass() + " to subscribing class "
                        + subscription.subscriber.getClass(), cause);
            }
            if (sendSubscriberExceptionEvent) {
                SubscriberExceptionEvent exEvent = new SubscriberExceptionEvent(this, cause, event,
                        subscription.subscriber);
                post(exEvent);
            }
        }
    }

    /** For ThreadLocal, much faster to set (and get multiple values). */
    final static class PostingThreadState {
        final List<Object> eventQueue = new ArrayList<>();
        boolean isPosting;
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;
    }

    ExecutorService getExecutorService() {
        return executorService;
    }

    /**
     * For internal use only.
     */
    public Logger getLogger() {
        return logger;
    }

    // Just an idea: we could provide a callback to post() to be notified, an alternative would be events, of course...
    /* public */interface PostCallback {
        void onPostCompleted(List<SubscriberExceptionEvent> exceptionEvents);
    }

    @Override
    public String toString() {
        return "EventBus[indexCount=" + indexCount + ", eventInheritance=" + eventInheritance + "]";
    }
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java
================================================
/*
 * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import org.greenrobot.eventbus.android.AndroidComponents;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.
 * Create a new builder using {@link EventBus#builder()}.
 */
@SuppressWarnings("unused")
public class EventBusBuilder {
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;
    List<SubscriberInfoIndex> subscriberInfoIndexes;
    Logger logger;
    MainThreadSupport mainThreadSupport;

    EventBusBuilder() {
    }

    /** Default: true */
    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }

    /** Default: true */
    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }

    /**
     * Fails if an subscriber throws an exception (default: false).
     * <p/>
     * Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss
     * exceptions during development.
     */
    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
        this.throwSubscriberException = throwSubscriberException;
        return this;
    }

    /**
     * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).
     * Switching this feature off will improve posting of events. For simple event classes extending Object directly,
     * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be
     * greater than 20%.
     * <p/>
     * However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,
     * unless it is posting at high rates, e.g. hundreds/thousands of events per second.
     */
    public EventBusBuilder eventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
        return this;
    }


    /**
     * Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced
     * setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.
     */
    public EventBusBuilder executorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    /**
     * Method name verification is done for methods starting with onEvent to avoid typos; using this method you can
     * exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor
     * abstract).
     */
    public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
        if (skipMethodVerificationForClasses == null) {
            skipMethodVerificationForClasses = new ArrayList<>();
        }
        skipMethodVerificationForClasses.add(clazz);
        return this;
    }

    /** Forces the use of reflection even if there's a generated index (default: false). */
    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
        return this;
    }

    /** Enables strict method verification (default: false). */
    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
        this.strictMethodVerification = strictMethodVerification;
        return this;
    }

    /** Adds an index generated by EventBus' annotation preprocessor. */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

    /**
     * Set a specific log handler for all EventBus logging.
     * <p/>
     * By default, all logging is via {@code android.util.Log} on Android or System.out on JVM.
     */
    public EventBusBuilder logger(Logger logger) {
        this.logger = logger;
        return this;
    }

    Logger getLogger() {
        if (logger != null) {
            return logger;
        } else {
            return Logger.Default.get();
        }
    }

    MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (AndroidComponents.areAvailable()) {
            return AndroidComponents.get().defaultMainThreadSupport;
        } else {
            return null;
        }
    }

    /**
     * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
     * done only once before the first usage of the default EventBus.
     *
     * @throws EventBusException if there's already a default EventBus instance in place
     */
    public EventBus installDefaultEventBus() {
        synchronized (EventBus.class) {
            if (EventBus.defaultInstance != null) {
                throw new EventBusException("Default instance already exists." +
                        " It may be only set once before it's used the first time to ensure consistent behavior.");
            }
            EventBus.defaultInstance = build();
            return EventBus.defaultInstance;
        }
    }

    /** Builds an EventBus based on the current configuration. */
    public EventBus build() {
        return new EventBus(this);
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/EventBusException.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

/**
 * An {@link RuntimeException} thrown in cases something went wrong inside EventBus.
 * 
 * @author Markus
 * 
 */
public class EventBusException extends RuntimeException {

    private static final long serialVersionUID = -2912559384646531479L;

    public EventBusException(String detailMessage) {
        super(detailMessage);
    }

    public EventBusException(Throwable throwable) {
        super(throwable);
    }

    public EventBusException(String detailMessage, Throwable throwable) {
        super(detailMessage, throwable);
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/Logger.java
================================================
/*
 * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import org.greenrobot.eventbus.android.AndroidComponents;
import java.util.logging.Level;

public interface Logger {

    void log(Level level, String msg);

    void log(Level level, String msg, Throwable th);

    class JavaLogger implements Logger {
        protected final java.util.logging.Logger logger;

        public JavaLogger(String tag) {
            logger = java.util.logging.Logger.getLogger(tag);
        }

        @Override
        public void log(Level level, String msg) {
            // TODO Replace logged method with caller method
            logger.log(level, msg);
        }

        @Override
        public void log(Level level, String msg, Throwable th) {
            // TODO Replace logged method with caller method
            logger.log(level, msg, th);
        }

    }

    class SystemOutLogger implements Logger {

        @Override
        public void log(Level level, String msg) {
            System.out.println("[" + level + "] " + msg);
        }

        @Override
        public void log(Level level, String msg, Throwable th) {
            System.out.println("[" + level + "] " + msg);
            th.printStackTrace(System.out);
        }

    }

    class Default {
        public static Logger get() {
            if (AndroidComponents.areAvailable()) {
                return AndroidComponents.get().logger;
            }

            return new SystemOutLogger();
        }
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

/**
 * Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's main thread is used.
 */
public interface MainThreadSupport {

    boolean isMainThread();

    Poster createPoster(EventBus eventBus);
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/NoSubscriberEvent.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

/**
 * This Event is posted by EventBus when no subscriber is found for a posted event.
 * 
 * @author Markus
 */
public final class NoSubscriberEvent {
    /** The {@link EventBus} instance to with the original event was posted to. */
    public final EventBus eventBus;

    /** The original event that could not be delivered to any subscriber. */
    public final Object originalEvent;

    public NoSubscriberEvent(EventBus eventBus, Object originalEvent) {
        this.eventBus = eventBus;
        this.originalEvent = originalEvent;
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/PendingPost.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import java.util.ArrayList;
import java.util.List;

final class PendingPost {
    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();

    Object event;
    Subscription subscription;
    PendingPost next;

    private PendingPost(Object event, Subscription subscription) {
        this.event = event;
        this.subscription = subscription;
    }

    static PendingPost obtainPendingPost(Subscription subscription, Object event) {
        synchronized (pendingPostPool) {
            int size = pendingPostPool.size();
            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
        return new PendingPost(event, subscription);
    }

    static void releasePendingPost(PendingPost pendingPost) {
        pendingPost.event = null;
        pendingPost.subscription = null;
        pendingPost.next = null;
        synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }

}

================================================
FILE: EventBus/src/org/greenrobot/eventbus/PendingPostQueue.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbus;

final class PendingPostQueue {
    private PendingPost head;
    private PendingPost tail;

    synchronized void enqueue(PendingPost pendingPost) {
        if (pendingPost == null) {
            throw new NullPointerException("null cannot be enqueued");
        }
        if (tail != null) {
            tail.next = pendingPost;
            tail = pendingPost;
        } else if (head == null) {
            head = tail = pendingPost;
        } else {
            throw new IllegalStateException("Head present, but no tail");
        }
        notifyAll();
    }

    synchronized PendingPost poll() {
        PendingPost pendingPost = head;
        if (head != null) {
            head = head.next;
            if (head == null) {
                tail = null;
            }
        }
        return pendingPost;
    }

    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
        if (head == null) {
            wait(maxMillisToWait);
        }
        return poll();
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/Poster.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

/**
 * Posts events.
 *
 * @author William Ferguson
 */
public interface Poster {

    /**
     * Enqueue an event to be posted for a particular subscription.
     *
     * @param subscription Subscription which will receive the event.
     * @param event        Event that will be posted to subscribers.
     */
    void enqueue(Subscription subscription, Object event);
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/Subscribe.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbus;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;

    /**
     * If true, delivers the most recent sticky event (posted with
     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
     */
    boolean sticky() default false;

    /** Subscriber priority to influence the order of event delivery.
     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
     * delivery among subscribers with different {@link ThreadMode}s! */
    int priority() default 0;
}



================================================
FILE: EventBus/src/org/greenrobot/eventbus/SubscriberExceptionEvent.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

/**
 * This Event is posted by EventBus when an exception occurs inside a subscriber's event handling method.
 * 
 * @author Markus
 */
public final class SubscriberExceptionEvent {
    /** The {@link EventBus} instance to with the original event was posted to. */
    public final EventBus eventBus;

    /** The Throwable thrown by a subscriber. */
    public final Throwable throwable;

    /** The original event that could not be delivered to any subscriber. */
    public final Object causingEvent;

    /** The subscriber that threw the Throwable. */
    public final Object causingSubscriber;

    public SubscriberExceptionEvent(EventBus eventBus, Throwable throwable, Object causingEvent,
            Object causingSubscriber) {
        this.eventBus = eventBus;
        this.throwable = throwable;
        this.causingEvent = causingEvent;
        this.causingSubscriber = causingSubscriber;
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/SubscriberMethod.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import java.lang.reflect.Method;

/** Used internally by EventBus and generated subscriber indexes. */
public class SubscriberMethod {
    final Method method;
    final ThreadMode threadMode;
    final Class<?> eventType;
    final int priority;
    final boolean sticky;
    /** Used for efficient comparison */
    String methodString;

    public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
        this.method = method;
        this.threadMode = threadMode;
        this.eventType = eventType;
        this.priority = priority;
        this.sticky = sticky;
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        } else if (other instanceof SubscriberMethod) {
            checkMethodString();
            SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;
            otherSubscriberMethod.checkMethodString();
            // Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
            return methodString.equals(otherSubscriberMethod.methodString);
        } else {
            return false;
        }
    }

    private synchronized void checkMethodString() {
        if (methodString == null) {
            // Method.toString has more overhead, just take relevant parts of the method
            StringBuilder builder = new StringBuilder(64);
            builder.append(method.getDeclaringClass().getName());
            builder.append('#').append(method.getName());
            builder.append('(').append(eventType.getName());
            methodString = builder.toString();
        }
    }

    @Override
    public int hashCode() {
        return method.hashCode();
    }
}

================================================
FILE: EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

class SubscriberMethodFinder {
    /*
     * In newer class files, compilers may add methods. Those are called bridge or synthetic methods.
     * EventBus must ignore both. There modifiers are not public but defined in the Java class file format:
     * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6-200-A.1
     */
    private static final int BRIDGE = 0x40;
    private static final int SYNTHETIC = 0x1000;

    private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;
    private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();

    private List<SubscriberInfoIndex> subscriberInfoIndexes;
    private final boolean strictMethodVerification;
    private final boolean ignoreGeneratedIndex;

    private static final int POOL_SIZE = 4;
    private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];

    SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,
                           boolean ignoreGeneratedIndex) {
        this.subscriberInfoIndexes = subscriberInfoIndexes;
        this.strictMethodVerification = strictMethodVerification;
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
    }

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        if (subscriberMethods.isEmpty()) {
            throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
        } else {
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }
    }

    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            findState.subscriberInfo = getSubscriberInfo(findState);
            if (findState.subscriberInfo != null) {
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                for (SubscriberMethod subscriberMethod : array) {
                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else {
                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }

    private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
        List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
        findState.recycle();
        synchronized (FIND_STATE_POOL) {
            for (int i = 0; i < POOL_SIZE; i++) {
                if (FIND_STATE_POOL[i] == null) {
                    FIND_STATE_POOL[i] = findState;
                    break;
                }
            }
        }
        return subscriberMethods;
    }

    private FindState prepareFindState() {
        synchronized (FIND_STATE_POOL) {
            for (int i = 0; i < POOL_SIZE; i++) {
                FindState state = FIND_STATE_POOL[i];
                if (state != null) {
                    FIND_STATE_POOL[i] = null;
                    return state;
                }
            }
        }
        return new FindState();
    }

    private SubscriberInfo getSubscriberInfo(FindState findState) {
        if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
            SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
            if (findState.clazz == superclassInfo.getSubscriberClass()) {
                return superclassInfo;
            }
        }
        if (subscriberInfoIndexes != null) {
            for (SubscriberInfoIndex index : subscriberInfoIndexes) {
                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                if (info != null) {
                    return info;
                }
            }
        }
        return null;
    }

    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            findUsingReflectionInSingleClass(findState);
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }

    private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            try {
                methods = findState.clazz.getMethods();
            } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
                String msg = "Could not inspect methods of " + findState.clazz.getName();
                if (ignoreGeneratedIndex) {
                    msg += ". Please consider using EventBus annotation processor to avoid reflection.";
                } else {
                    msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
                }
                throw new EventBusException(msg, error);
            }
            findState.skipSuperClasses = true;
        }
        for (Method method : methods) {
            int modifiers = method.getModifiers();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                    String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                    throw new EventBusException("@Subscribe method " + methodName +
                            "must have exactly 1 parameter but has " + parameterTypes.length);
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException(methodName +
                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
            }
        }
    }

    static void clearCaches() {
        METHOD_CACHE.clear();
    }

    static class FindState {
        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
        final Map<Class, Object> anyMethodByEventType = new HashMap<>();
        final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
        final StringBuilder methodKeyBuilder = new StringBuilder(128);

        Class<?> subscriberClass;
        Class<?> clazz;
        boolean skipSuperClasses;
        SubscriberInfo subscriberInfo;

        void initForSubscriber(Class<?> subscriberClass) {
            this.subscriberClass = clazz = subscriberClass;
            skipSuperClasses = false;
            subscriberInfo = null;
        }

        void recycle() {
            subscriberMethods.clear();
            anyMethodByEventType.clear();
            subscriberClassByMethodKey.clear();
            methodKeyBuilder.setLength(0);
            subscriberClass = null;
            clazz = null;
            skipSuperClasses = false;
            subscriberInfo = null;
        }

        boolean checkAdd(Method method, Class<?> eventType) {
            // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
            // Usually a subscriber doesn't have methods listening to the same event type.
            Object existing = anyMethodByEventType.put(eventType, method);
            if (existing == null) {
                return true;
            } else {
                if (existing instanceof Method) {
                    if (!checkAddWithMethodSignature((Method) existing, eventType)) {
                        // Paranoia check
                        throw new IllegalStateException();
                    }
                    // Put any non-Method object to "consume" the existing Method
                    anyMethodByEventType.put(eventType, this);
                }
                return checkAddWithMethodSignature(method, eventType);
            }
        }

        private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
            methodKeyBuilder.setLength(0);
            methodKeyBuilder.append(method.getName());
            methodKeyBuilder.append('>').append(eventType.getName());

            String methodKey = methodKeyBuilder.toString();
            Class<?> methodClass = method.getDeclaringClass();
            Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
            if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
                // Only add if not already found in a sub class
                return true;
            } else {
                // Revert the put, old class is further down the class hierarchy
                subscriberClassByMethodKey.put(methodKey, methodClassOld);
                return false;
            }
        }

        void moveToSuperclass() {
            if (skipSuperClasses) {
                clazz = null;
            } else {
                clazz = clazz.getSuperclass();
                String clazzName = clazz.getName();
                // Skip system classes, this degrades performance.
                // Also we might avoid some ClassNotFoundException (see FAQ for background).
                if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") ||
                        clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) {
                    clazz = null;
                }
            }
        }
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/Subscription.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

final class Subscription {
    final Object subscriber;
    final SubscriberMethod subscriberMethod;
    /**
     * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
     * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
     */
    volatile boolean active;

    Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
        this.subscriber = subscriber;
        this.subscriberMethod = subscriberMethod;
        active = true;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Subscription) {
            Subscription otherSubscription = (Subscription) other;
            return subscriber == otherSubscription.subscriber
                    && subscriberMethod.equals(otherSubscription.subscriberMethod);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
    }
}

================================================
FILE: EventBus/src/org/greenrobot/eventbus/ThreadMode.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

/**
 * Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus.
 * EventBus takes care of threading independently of the posting thread.
 *
 * @see EventBus#register(Object)
 */
public enum ThreadMode {
    /**
     * This is the default. Subscriber will be called directly in the same thread, which is posting the event. Event delivery
     * implies the least overhead because it avoids thread switching completely. Thus, this is the recommended mode for
     * simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers
     * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
     */
    POSTING,

    /**
     * On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is
     * the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event
     * is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.
     * <p>
     * If not on Android, behaves the same as {@link #POSTING}.
     */
    MAIN,

    /**
     * On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},
     * the event will always be queued for delivery. This ensures that the post call is non-blocking.
     * <p>
     * If not on Android, behaves the same as {@link #POSTING}.
     */
    MAIN_ORDERED,

    /**
     * On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods
     * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
     * background thread, that will deliver all its events sequentially. Subscribers using this mode should try to
     * return quickly to avoid blocking the background thread.
     * <p>
     * If not on Android, always uses a background thread.
     */
    BACKGROUND,

    /**
     * Subscriber will be called in a separate thread. This is always independent of the posting thread and the
     * main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should
     * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
     * of long-running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus
     * uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.
     */
    ASYNC
}

================================================
FILE: EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java
================================================
package org.greenrobot.eventbus.android;

import org.greenrobot.eventbus.Logger;
import org.greenrobot.eventbus.MainThreadSupport;

public abstract class AndroidComponents {

    private static final AndroidComponents implementation;

    static {
        implementation = AndroidDependenciesDetector.isAndroidSDKAvailable()
            ? AndroidDependenciesDetector.instantiateAndroidComponents()
            : null;
    }

    public static boolean areAvailable() {
        return implementation != null;
    }

    public static AndroidComponents get() {
        return implementation;
    }

    public final Logger logger;
    public final MainThreadSupport defaultMainThreadSupport;

    public AndroidComponents(Logger logger, MainThreadSupport defaultMainThreadSupport) {
        this.logger = logger;
        this.defaultMainThreadSupport = defaultMainThreadSupport;
    }
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java
================================================
package org.greenrobot.eventbus.android;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@SuppressWarnings("TryWithIdenticalCatches")
public class AndroidDependenciesDetector {

    public static boolean isAndroidSDKAvailable() {

        try {
            Class<?> looperClass = Class.forName("android.os.Looper");
            Method getMainLooper = looperClass.getDeclaredMethod("getMainLooper");
            Object mainLooper = getMainLooper.invoke(null);
            return mainLooper != null;
        }
        catch (ClassNotFoundException ignored) {}
        catch (NoSuchMethodException ignored) {}
        catch (IllegalAccessException ignored) {}
        catch (InvocationTargetException ignored) {}

        return false;
    }

    private static final String ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME = "org.greenrobot.eventbus.android.AndroidComponentsImpl";

    public static boolean areAndroidComponentsAvailable() {

        try {
            Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
            return true;
        }
        catch (ClassNotFoundException ex) {
            return false;
        }
    }

    public static AndroidComponents instantiateAndroidComponents() {

        try {
            Class<?> impl = Class.forName(ANDROID_COMPONENTS_IMPLEMENTATION_CLASS_NAME);
            return (AndroidComponents) impl.getConstructor().newInstance();
        }
        catch (Throwable ex) {
            return null;
        }
    }
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.meta;

import org.greenrobot.eventbus.EventBusException;
import org.greenrobot.eventbus.SubscriberMethod;
import org.greenrobot.eventbus.ThreadMode;

import java.lang.reflect.Method;

/** Base class for generated subscriber meta info classes created by annotation processing. */
public abstract class AbstractSubscriberInfo implements SubscriberInfo {
    private final Class subscriberClass;
    private final Class<? extends SubscriberInfo> superSubscriberInfoClass;
    private final boolean shouldCheckSuperclass;

    protected AbstractSubscriberInfo(Class subscriberClass, Class<? extends SubscriberInfo> superSubscriberInfoClass,
                                     boolean shouldCheckSuperclass) {
        this.subscriberClass = subscriberClass;
        this.superSubscriberInfoClass = superSubscriberInfoClass;
        this.shouldCheckSuperclass = shouldCheckSuperclass;
    }

    @Override
    public Class getSubscriberClass() {
        return subscriberClass;
    }

    @Override
    public SubscriberInfo getSuperSubscriberInfo() {
        if(superSubscriberInfoClass == null) {
            return null;
        }
        try {
            return superSubscriberInfoClass.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean shouldCheckSuperclass() {
        return shouldCheckSuperclass;
    }

    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType) {
        return createSubscriberMethod(methodName, eventType, ThreadMode.POSTING, 0, false);
    }

    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode) {
        return createSubscriberMethod(methodName, eventType, threadMode, 0, false);
    }

    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
                                                      int priority, boolean sticky) {
        try {
            Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
            return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
        } catch (NoSuchMethodException e) {
            throw new EventBusException("Could not find subscriber method in " + subscriberClass +
                    ". Maybe a missing ProGuard rule?", e);
        }
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SimpleSubscriberInfo.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.meta;

import org.greenrobot.eventbus.SubscriberMethod;

/**
 * Uses {@link SubscriberMethodInfo} objects to create {@link org.greenrobot.eventbus.SubscriberMethod} objects on demand.
 */
public class SimpleSubscriberInfo extends AbstractSubscriberInfo {

    private final SubscriberMethodInfo[] methodInfos;

    public SimpleSubscriberInfo(Class subscriberClass, boolean shouldCheckSuperclass, SubscriberMethodInfo[] methodInfos) {
        super(subscriberClass, null, shouldCheckSuperclass);
        this.methodInfos = methodInfos;
    }

    @Override
    public synchronized SubscriberMethod[] getSubscriberMethods() {
        int length = methodInfos.length;
        SubscriberMethod[] methods = new SubscriberMethod[length];
        for (int i = 0; i < length; i++) {
            SubscriberMethodInfo info = methodInfos[i];
            methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,
                    info.priority, info.sticky);
        }
        return methods;
    }
}

================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfo.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.meta;

import org.greenrobot.eventbus.SubscriberMethod;

/** Base class for generated index classes created by annotation processing. */
public interface SubscriberInfo {
    Class<?> getSubscriberClass();

    SubscriberMethod[] getSubscriberMethods();

    SubscriberInfo getSuperSubscriberInfo();

    boolean shouldCheckSuperclass();
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfoIndex.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.meta;

/**
 * Interface for generated indexes.
 */
public interface SubscriberInfoIndex {
    SubscriberInfo getSubscriberInfo(Class<?> subscriberClass);
}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberMethodInfo.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.meta;

import org.greenrobot.eventbus.ThreadMode;

public class SubscriberMethodInfo {
    final String methodName;
    final ThreadMode threadMode;
    final Class<?> eventType;
    final int priority;
    final boolean sticky;

    public SubscriberMethodInfo(String methodName, Class<?> eventType, ThreadMode threadMode,
                                int priority, boolean sticky) {
        this.methodName = methodName;
        this.threadMode = threadMode;
        this.eventType = eventType;
        this.priority = priority;
        this.sticky = sticky;
    }

    public SubscriberMethodInfo(String methodName, Class<?> eventType) {
        this(methodName, eventType, ThreadMode.POSTING, 0, false);
    }

    public SubscriberMethodInfo(String methodName, Class<?> eventType, ThreadMode threadMode) {
        this(methodName, eventType, threadMode, 0, false);
    }

}

================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.util;

import org.greenrobot.eventbus.EventBus;

import java.lang.reflect.Constructor;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Level;

/**
 * Executes an {@link RunnableEx} using a thread pool. Thrown exceptions are propagated by posting failure events.
 * By default, uses {@link ThrowableFailureEvent}.
 * <p>
 * Set a custom event type using {@link Builder#failureEventType(Class)}.
 * The failure event class must have a constructor with one parameter of type {@link Throwable}.
 * If using ProGuard or R8 make sure the constructor of the failure event class is kept, it is accessed via reflection.
 * E.g. add a rule like
 * <pre>
 * -keepclassmembers class com.example.CustomThrowableFailureEvent {
 *     &lt;init&gt;(java.lang.Throwable);
 * }
 * </pre>
 */
public class AsyncExecutor {

    public static class Builder {
        private Executor threadPool;
        private Class<?> failureEventType;
        private EventBus eventBus;

        private Builder() {
        }

        public Builder threadPool(Executor threadPool) {
            this.threadPool = threadPool;
            return this;
        }

        public Builder failureEventType(Class<?> failureEventType) {
            this.failureEventType = failureEventType;
            return this;
        }

        public Builder eventBus(EventBus eventBus) {
            this.eventBus = eventBus;
            return this;
        }

        public AsyncExecutor build() {
            return buildForScope(null);
        }

        public AsyncExecutor buildForScope(Object executionContext) {
            if (eventBus == null) {
                eventBus = EventBus.getDefault();
            }
            if (threadPool == null) {
                threadPool = Executors.newCachedThreadPool();
            }
            if (failureEventType == null) {
                failureEventType = ThrowableFailureEvent.class;
            }
            return new AsyncExecutor(threadPool, eventBus, failureEventType, executionContext);
        }
    }

    /** Like {@link Runnable}, but the run method may throw an exception. */
    public interface RunnableEx {
        void run() throws Exception;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static AsyncExecutor create() {
        return new Builder().build();
    }

    private final Executor threadPool;
    private final Constructor<?> failureEventConstructor;
    private final EventBus eventBus;
    private final Object scope;

    private AsyncExecutor(Executor threadPool, EventBus eventBus, Class<?> failureEventType, Object scope) {
        this.threadPool = threadPool;
        this.eventBus = eventBus;
        this.scope = scope;
        try {
            failureEventConstructor = failureEventType.getConstructor(Throwable.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(
                    "Failure event class must have a constructor with one parameter of type Throwable", e);
        }
    }

    /** Posts an failure event if the given {@link RunnableEx} throws an Exception. */
    public void execute(final RunnableEx runnable) {
        threadPool.execute(() -> {
            try {
                runnable.run();
            } catch (Exception e) {
                Object event;
                try {
                    event = failureEventConstructor.newInstance(e);
                } catch (Exception e1) {
                    eventBus.getLogger().log(Level.SEVERE, "Original exception:", e);
                    throw new RuntimeException("Could not create failure event", e1);
                }
                if (event instanceof HasExecutionScope) {
                    ((HasExecutionScope) event).setExecutionScope(scope);
                }
                eventBus.post(event);
            }
        });
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java
================================================
/*
 * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbus.util;

import org.greenrobot.eventbus.Logger;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;


/**
 * Maps throwables to texts for error dialogs. Use Config to configure the mapping.
 * 
 * @author Markus
 */
public class ExceptionToResourceMapping {

    public final Map<Class<? extends Throwable>, Integer> throwableToMsgIdMap;

    public ExceptionToResourceMapping() {
        throwableToMsgIdMap = new HashMap<>();
    }

    /** Looks at the exception and its causes trying to find an ID. */
    public Integer mapThrowable(final Throwable throwable) {
        Throwable throwableToCheck = throwable;
        int depthToGo = 20;

        while (true) {
            Integer resId = mapThrowableFlat(throwableToCheck);
            if (resId != null) {
                return resId;
            } else {
                throwableToCheck = throwableToCheck.getCause();
                depthToGo--;
                if (depthToGo <= 0 || throwableToCheck == throwable || throwableToCheck == null) {
                    Logger logger = Logger.Default.get();  // No EventBus instance here
                    logger.log(Level.FINE, "No specific message resource ID found for " + throwable);
                    // return config.defaultErrorMsgId;
                    return null;
                }
            }
        }

    }

    /** Mapping without checking the cause (done in mapThrowable). */
    protected Integer mapThrowableFlat(Throwable throwable) {
        Class<? extends Throwable> throwableClass = throwable.getClass();
        Integer resId = throwableToMsgIdMap.get(throwableClass);
        if (resId == null) {
            Class<? extends Throwable> closestClass = null;
            Set<Entry<Class<? extends Throwable>, Integer>> mappings = throwableToMsgIdMap.entrySet();
            for (Entry<Class<? extends Throwable>, Integer> mapping : mappings) {
                Class<? extends Throwable> candidate = mapping.getKey();
                if (candidate.isAssignableFrom(throwableClass)) {
                    if (closestClass == null || closestClass.isAssignableFrom(candidate)) {
                        closestClass = candidate;
                        resId = mapping.getValue();
                    }
                }
            }

        }
        return resId;
    }

    public ExceptionToResourceMapping addMapping(Class<? extends Throwable> clazz, int msgId) {
        throwableToMsgIdMap.put(clazz, msgId);
        return this;
    }

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/HasExecutionScope.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbus.util;

public interface HasExecutionScope {
    Object getExecutionScope();

    void setExecutionScope(Object executionScope);

}


================================================
FILE: EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.util;

/**
 * A generic failure event, which can be used by apps to propagate thrown exceptions.
 * Used as default failure event by {@link AsyncExecutor}.
 */
public class ThrowableFailureEvent implements HasExecutionScope {
    protected final Throwable throwable;
    protected final boolean suppressErrorUi;
    private Object executionContext;

    public ThrowableFailureEvent(Throwable throwable) {
        this.throwable = throwable;
        suppressErrorUi = false;
    }

    /**
     * @param suppressErrorUi
     *            true indicates to the receiver that no error UI (e.g. dialog) should now displayed.
     */
    public ThrowableFailureEvent(Throwable throwable, boolean suppressErrorUi) {
        this.throwable = throwable;
        this.suppressErrorUi = suppressErrorUi;
    }

    public Throwable getThrowable() {
        return throwable;
    }

    public boolean isSuppressErrorUi() {
        return suppressErrorUi;
    }

    public Object getExecutionScope() {
        return executionContext;
    }

    public void setExecutionScope(Object executionContext) {
        this.executionContext = executionContext;
    }
    
}


================================================
FILE: EventBusAnnotationProcessor/build.gradle
================================================
apply plugin: 'java'

group = rootProject.group
version = rootProject.version

java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8

dependencies {
    implementation project(':eventbus-java')
    implementation 'de.greenrobot:java-common:2.3.1'

    // Generates the required META-INF descriptor to make the processor incremental.
    def incap = '0.2'
    compileOnly "net.ltgt.gradle.incap:incap:$incap"
    annotationProcessor "net.ltgt.gradle.incap:incap-processor:$incap"
}

sourceSets {
    main {
        java {
            srcDir 'src'
        }
        resources {
            srcDir 'res'
        }
    }
}

javadoc {
    title = "EventBus Annotation Processor ${version} API"
	options.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>'
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    archiveClassifier.set("javadoc")
    from 'build/docs/javadoc'
}

task sourcesJar(type: Jar) {
    archiveClassifier.set("sources")
    from sourceSets.main.allSource
}

apply from: rootProject.file("gradle/publish.gradle")
// Set project-specific properties
afterEvaluate {
    publishing.publications {
        mavenJava(MavenPublication) {
            artifactId = "eventbus-annotation-processor"

            from components.java
            artifact javadocJar
            artifact sourcesJar
            pom {
                name = "EventBus Annotation Processor"
                description = "Precompiler for EventBus Annotations."
                packaging = "jar"
            }
        }
    }
}


================================================
FILE: EventBusAnnotationProcessor/res/META-INF/services/javax.annotation.processing.Processor
================================================
org.greenrobot.eventbus.annotationprocessor.EventBusAnnotationProcessor


================================================
FILE: EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus.annotationprocessor;

import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;

import de.greenrobot.common.ListMap;


import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING;

/**
 * Is an aggregating processor as it writes a single file, the subscriber index file,
 * based on found elements with the @Subscriber annotation.
 */
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
@IncrementalAnnotationProcessor(AGGREGATING)
public class EventBusAnnotationProcessor extends AbstractProcessor {
    public static final String OPTION_EVENT_BUS_INDEX = "eventBusIndex";
    public static final String OPTION_VERBOSE = "verbose";

    /** Found subscriber methods for a class (without superclasses). */
    private final ListMap<TypeElement, ExecutableElement> methodsByClass = new ListMap<>();
    private final Set<TypeElement> classesToSkip = new HashSet<>();

    private boolean writerRoundDone;
    private int round;
    private boolean verbose;

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
        Messager messager = processingEnv.getMessager();
        try {
            String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
            if (index == null) {
                messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
                        " passed to annotation processor");
                return false;
            }
            verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));
            int lastPeriod = index.lastIndexOf('.');
            String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;

            round++;
            if (verbose) {
                messager.printMessage(Diagnostic.Kind.NOTE, "Processing round " + round + ", new annotations: " +
                        !annotations.isEmpty() + ", processingOver: " + env.processingOver());
            }
            if (env.processingOver()) {
                if (!annotations.isEmpty()) {
                    messager.printMessage(Diagnostic.Kind.ERROR,
                            "Unexpected processing state: annotations still available after processing over");
                    return false;
                }
            }
            if (annotations.isEmpty()) {
                return false;
            }

            if (writerRoundDone) {
                messager.printMessage(Diagnostic.Kind.ERROR,
                        "Unexpected processing state: annotations still available after writing.");
            }
            collectSubscribers(annotations, env, messager);
            checkForSubscribersToSkip(messager, indexPackage);

            if (!methodsByClass.isEmpty()) {
                createInfoIndexFile(index);
            } else {
                messager.printMessage(Diagnostic.Kind.WARNING, "No @Subscribe annotations found");
            }
            writerRoundDone = true;
        } catch (RuntimeException e) {
            // IntelliJ does not handle exceptions nicely, so log and print a message
            e.printStackTrace();
            messager.printMessage(Diagnostic.Kind.ERROR, "Unexpected error in EventBusAnnotationProcessor: " + e);
        }
        return true;
    }

    private void collectSubscribers(Set<? extends TypeElement> annotations, RoundEnvironment env, Messager messager) {
        for (TypeElement annotation : annotations) {
            Set<? extends Element> elements = env.getElementsAnnotatedWith(annotation);
            for (Element element : elements) {
                if (element instanceof ExecutableElement) {
                    ExecutableElement method = (ExecutableElement) element;
                    if (checkHasNoErrors(method, messager)) {
                        TypeElement classElement = (TypeElement) method.getEnclosingElement();
                        methodsByClass.putElement(classElement, method);
                    }
                } else {
                    messager.printMessage(Diagnostic.Kind.ERROR, "@Subscribe is only valid for methods", element);
                }
            }
        }
    }

    private boolean checkHasNoErrors(ExecutableElement element, Messager messager) {
        if (element.getModifiers().contains(Modifier.STATIC)) {
            messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must not be static", element);
            return false;
        }

        if (!element.getModifiers().contains(Modifier.PUBLIC)) {
            messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must be public", element);
            return false;
        }

        List<? extends VariableElement> parameters = ((ExecutableElement) element).getParameters();
        if (parameters.size() != 1) {
            messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must have exactly 1 parameter", element);
            return false;
        }
        return true;
    }

    /**
     * Subscriber classes should be skipped if their class or any involved event class are not visible to the index.
     */
    private void checkForSubscribersToSkip(Messager messager, String myPackage) {
        for (TypeElement skipCandidate : methodsByClass.keySet()) {
            TypeElement subscriberClass = skipCandidate;
            while (subscriberClass != null) {
                if (!isVisible(myPackage, subscriberClass)) {
                    boolean added = classesToSkip.add(skipCandidate);
                    if (added) {
                        String msg;
                        if (subscriberClass.equals(skipCandidate)) {
                            msg = "Falling back to reflection because class is not public";
                        } else {
                            msg = "Falling back to reflection because " + skipCandidate +
                                    " has a non-public super class";
                        }
                        messager.printMessage(Diagnostic.Kind.NOTE, msg, subscriberClass);
                    }
                    break;
                }
                List<ExecutableElement> methods = methodsByClass.get(subscriberClass);
                if (methods != null) {
                    for (ExecutableElement method : methods) {
                        String skipReason = null;
                        VariableElement param = method.getParameters().get(0);
                        TypeMirror typeMirror = getParamTypeMirror(param, messager);
                        if (!(typeMirror instanceof DeclaredType) ||
                                !(((DeclaredType) typeMirror).asElement() instanceof TypeElement)) {
                            skipReason = "event type cannot be processed";
                        }
                        if (skipReason == null) {
                            TypeElement eventTypeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
                            if (!isVisible(myPackage, eventTypeElement)) {
                                skipReason = "event type is not public";
                            }
                        }
                        if (skipReason != null) {
                            boolean added = classesToSkip.add(skipCandidate);
                            if (added) {
                                String msg = "Falling back to reflection because " + skipReason;
                                if (!subscriberClass.equals(skipCandidate)) {
                                    msg += " (found in super class for " + skipCandidate + ")";
                                }
                                messager.printMessage(Diagnostic.Kind.NOTE, msg, param);
                            }
                            break;
                        }
                    }
                }
                subscriberClass = getSuperclass(subscriberClass);
            }
        }
    }

    private TypeMirror getParamTypeMirror(VariableElement param, Messager messager) {
        TypeMirror typeMirror = param.asType();
        // Check for generic type
        if (typeMirror instanceof TypeVariable) {
            TypeMirror upperBound = ((TypeVariable) typeMirror).getUpperBound();
            if (upperBound instanceof DeclaredType) {
                if (messager != null) {
                    messager.printMessage(Diagnostic.Kind.NOTE, "Using upper bound type " + upperBound +
                            " for generic parameter", param);
                }
                typeMirror = upperBound;
            }
        }
        return typeMirror;
    }

    private TypeElement getSuperclass(TypeElement type) {
        if (type.getSuperclass().getKind() == TypeKind.DECLARED) {
            TypeElement superclass = (TypeElement) processingEnv.getTypeUtils().asElement(type.getSuperclass());
            String name = superclass.getQualifiedName().toString();
            if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
                // Skip system classes, this just degrades performance
                return null;
            } else {
                return superclass;
            }
        } else {
            return null;
        }
    }

    private String getClassString(TypeElement typeElement, String myPackage) {
        PackageElement packageElement = getPackageElement(typeElement);
        String packageString = packageElement.getQualifiedName().toString();
        String className = typeElement.getQualifiedName().toString();
        if (packageString != null && !packageString.isEmpty()) {
            if (packageString.equals(myPackage)) {
                className = cutPackage(myPackage, className);
            } else if (packageString.equals("java.lang")) {
                className = typeElement.getSimpleName().toString();
            }
        }
        return className;
    }

    private String cutPackage(String paket, String className) {
        if (className.startsWith(paket + '.')) {
            // Don't use TypeElement.getSimpleName, it doesn't work for us with inner classes
            return className.substring(paket.length() + 1);
        } else {
            // Paranoia
            throw new IllegalStateException("Mismatching " + paket + " vs. " + className);
        }
    }

    private PackageElement getPackageElement(TypeElement subscriberClass) {
        Element candidate = subscriberClass.getEnclosingElement();
        while (!(candidate instanceof PackageElement)) {
            candidate = candidate.getEnclosingElement();
        }
        return (PackageElement) candidate;
    }

    private void writeCreateSubscriberMethods(BufferedWriter writer, List<ExecutableElement> methods,
                                              String callPrefix, String myPackage) throws IOException {
        for (ExecutableElement method : methods) {
            List<? extends VariableElement> parameters = method.getParameters();
            TypeMirror paramType = getParamTypeMirror(parameters.get(0), null);
            TypeElement paramElement = (TypeElement) processingEnv.getTypeUtils().asElement(paramType);
            String methodName = method.getSimpleName().toString();
            String eventClass = getClassString(paramElement, myPackage) + ".class";

            Subscribe subscribe = method.getAnnotation(Subscribe.class);
            List<String> parts = new ArrayList<>();
            parts.add(callPrefix + "(\"" + methodName + "\",");
            String lineEnd = "),";
            if (subscribe.priority() == 0 && !subscribe.sticky()) {
                if (subscribe.threadMode() == ThreadMode.POSTING) {
                    parts.add(eventClass + lineEnd);
                } else {
                    parts.add(eventClass + ",");
                    parts.add("ThreadMode." + subscribe.threadMode().name() + lineEnd);
                }
            } else {
                parts.add(eventClass + ",");
                parts.add("ThreadMode." + subscribe.threadMode().name() + ",");
                parts.add(subscribe.priority() + ",");
                parts.add(subscribe.sticky() + lineEnd);
            }
            writeLine(writer, 3, parts.toArray(new String[parts.size()]));

            if (verbose) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Indexed @Subscribe at " +
                        method.getEnclosingElement().getSimpleName() + "." + methodName +
                        "(" + paramElement.getSimpleName() + ")");
            }

        }
    }

    private void createInfoIndexFile(String index) {
        BufferedWriter writer = null;
        try {
            JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);
            int period = index.lastIndexOf('.');
            String myPackage = period > 0 ? index.substring(0, period) : null;
            String clazz = index.substring(period + 1);
            writer = new BufferedWriter(sourceFile.openWriter());
            if (myPackage != null) {
                writer.write("package " + myPackage + ";\n\n");
            }
            writer.write("import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\n");
            writer.write("import org.greenrobot.eventbus.ThreadMode;\n\n");
            writer.write("import java.util.HashMap;\n");
            writer.write("import java.util.Map;\n\n");
            writer.write("/** This class is generated by EventBus, do not edit. */\n");
            writer.write("public class " + clazz + " implements SubscriberInfoIndex {\n");
            writer.write("    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;\n\n");
            writer.write("    static {\n");
            writer.write("        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();\n\n");
            writeIndexLines(writer, myPackage);
            writer.write("    }\n\n");
            writer.write("    private static void putIndex(SubscriberInfo info) {\n");
            writer.write("        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\n");
            writer.write("    }\n\n");
            writer.write("    @Override\n");
            writer.write("    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {\n");
            writer.write("        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);\n");
            writer.write("        if (info != null) {\n");
            writer.write("            return info;\n");
            writer.write("        } else {\n");
            writer.write("            return null;\n");
            writer.write("        }\n");
            writer.write("    }\n");
            writer.write("}\n");
        } catch (IOException e) {
            throw new RuntimeException("Could not write source for " + index, e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    //Silent
                }
            }
        }
    }

    private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {
        for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {
            if (classesToSkip.contains(subscriberTypeElement)) {
                continue;
            }

            String subscriberClass = getClassString(subscriberTypeElement, myPackage);
            if (isVisible(myPackage, subscriberTypeElement)) {
                writeLine(writer, 2,
                        "putIndex(new SimpleSubscriberInfo(" + subscriberClass + ".class,",
                        "true,", "new SubscriberMethodInfo[] {");
                List<ExecutableElement> methods = methodsByClass.get(subscriberTypeElement);
                writeCreateSubscriberMethods(writer, methods, "new SubscriberMethodInfo", myPackage);
                writer.write("        }));\n\n");
            } else {
                writer.write("        // Subscriber not visible to index: " + subscriberClass + "\n");
            }
        }
    }

    private boolean isVisible(String myPackage, TypeElement typeElement) {
        Set<Modifier> modifiers = typeElement.getModifiers();
        boolean visible;
        if (modifiers.contains(Modifier.PUBLIC)) {
            visible = true;
        } else if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.PROTECTED)) {
            visible = false;
        } else {
            String subscriberPackage = getPackageElement(typeElement).getQualifiedName().toString();
            if (myPackage == null) {
                visible = subscriberPackage.length() == 0;
            } else {
                visible = myPackage.equals(subscriberPackage);
            }
        }
        return visible;
    }

    private void writeLine(BufferedWriter writer, int indentLevel, String... parts) throws IOException {
        writeLine(writer, indentLevel, 2, parts);
    }

    private void writeLine(BufferedWriter writer, int indentLevel, int indentLevelIncrease, String... parts)
            throws IOException {
        writeIndent(writer, indentLevel);
        int len = indentLevel * 4;
        for (int i = 0; i < parts.length; i++) {
            String part = parts[i];
            if (i != 0) {
                if (len + part.length() > 118) {
                    writer.write("\n");
                    if (indentLevel < 12) {
                        indentLevel += indentLevelIncrease;
                    }
                    writeIndent(writer, indentLevel);
                    len = indentLevel * 4;
                } else {
                    writer.write(" ");
                }
            }
            writer.write(part);
            len += part.length();
        }
        writer.write("\n");
    }

    private void writeIndent(BufferedWriter writer, int indentLevel) throws IOException {
        for (int i = 0; i < indentLevel; i++) {
            writer.write("    ");
        }
    }
}


================================================
FILE: EventBusPerformance/.gitignore
================================================
/bin
/gen


================================================
FILE: EventBusPerformance/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.greenrobot.eventbusperf">

    <uses-feature
        android:name="android.hardware.touchscreen"
        android:required="false" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name="org.greenrobot.eventbusperf.TestSetupActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="org.greenrobot.eventbusperf.TestRunnerActivity"
            android:label="@string/app_name"
            android:process="de.greenrobot.eventperf.benchmark" >
        </activity>
    </application>

</manifest>

================================================
FILE: EventBusPerformance/build.gradle
================================================
buildscript {
    repositories {
        google()
        mavenCentral()
    }

    dependencies {
        // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1
        classpath 'com.android.tools.build:gradle:4.1.3'
    }
}

apply plugin: 'com.android.application'

dependencies {
    implementation project(':eventbus-android')
    annotationProcessor project(':eventbus-annotation-processor')
    implementation 'com.squareup:otto:1.3.8'
}

android {
    compileSdkVersion _compileSdkVersion

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            res.srcDirs = ['res']
        }
    }

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 26
        versionCode 1
        versionName "2.0.0"
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex']
            }
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}


================================================
FILE: EventBusPerformance/proguard-project.txt
================================================
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: EventBusPerformance/project.properties
================================================
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt

# Project target.
target=android-17


================================================
FILE: EventBusPerformance/res/layout/activity_runtests.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textViewTestRunning"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="#88333333"
        android:gravity="center"
        android:padding="15dp"
        android:text="@string/testIsRunning"
        android:textColor="#ffffff"
        android:textSize="30sp"
        android:textStyle="bold" />

    <ScrollView
        android:id="@+id/scrollViewResults"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@+id/buttonCancel"
        android:fillViewport="true" >

        <TextView
            android:id="@+id/textViewResult"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textSize="16sp" />
    </ScrollView>

    <Button
        android:id="@+id/buttonCancel"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/buttonKillProcess"
        android:layout_alignWithParentIfMissing="true"
        android:layout_margin="16dp"
        android:onClick="onClickCancel"
        android:text="@string/buttonCancel" />

    <Button
        android:id="@+id/buttonKillProcess"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_margin="16dp"
        android:onClick="onClickKillProcess"
        android:text="@string/buttonKillProcess"
        android:visibility="gone" />

</RelativeLayout>

================================================
FILE: EventBusPerformance/res/layout/activity_setuptests.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:focusableInTouchMode="true"
    android:orientation="vertical" >

    <Spinner
        android:id="@+id/spinnerTestToRun"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="14dp"
        android:entries="@array/spinnerTestsToRun" />

    <ScrollView
        android:id="@+id/scrollViewSettings"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

        <LinearLayout
            android:id="@+id/LinearLayout2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="16dp"
            android:paddingRight="16dp" >

            <CheckBox
                android:id="@+id/checkBoxEventBus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:checked="true"
                android:onClick="checkEventBus"
                android:text="@string/test_eventBus" />

            <Spinner
                android:id="@+id/spinnerThread"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="48dp"
                android:entries="@array/spinnerThreadModes" />

            <CheckBox
                android:id="@+id/checkBoxEventBusEventHierarchy"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:checked="true"
                android:onClick="checkEventBus"
                android:layout_marginLeft="48dp"
                android:text="@string/test_eventBusEventHierarchy" />

            <CheckBox
                android:id="@+id/checkBoxEventBusIgnoreGeneratedIndex"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="checkEventBus"
                android:layout_marginLeft="48dp"
                android:text="@string/test_eventBusEventIgnoreGeneratedIndex" />

            <CheckBox
                android:id="@+id/checkBoxOtto"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:checked="true"
                android:layout_marginTop="16dp"
                android:text="@string/test_otto" />


            <CheckBox
                android:id="@+id/checkBoxBroadcast"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/test_broadcast"
                android:visibility="gone" />


            <CheckBox
                android:id="@+id/checkBoxLocalBroadcast"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="32dp"
                android:text="@string/test_localBroadcast"
                android:visibility="gone" />

            <RelativeLayout
                android:id="@+id/relativeLayoutForEvents"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginBottom="18dp" >

                <EditText
                    android:id="@+id/editTextEvent"
                    android:layout_width="90dp"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:inputType="number"
                    android:text="1000" />

                <TextView
                    android:id="@+id/eventView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignBaseline="@+id/editTextEvent"
                    android:layout_alignParentLeft="true"
                    android:layout_toLeftOf="@+id/editTextEvent"
                    android:text="@string/eventViewText" />
            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/relativeLayoutForSubscribers"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginBottom="8dp" >

                <EditText
                    android:id="@+id/editTextSubscribe"
                    android:layout_width="90dp"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:inputType="number"
                    android:text="1" />

                <TextView
                    android:id="@+id/subscribe"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignBaseline="@+id/editTextSubscribe"
                    android:layout_alignParentLeft="true"
                    android:layout_toLeftOf="@+id/editTextSubscribe"
                    android:text="@string/subscriberViewText" />
            </RelativeLayout>
        </LinearLayout>
    </ScrollView>

    <Button
        android:id="@+id/buttonStart"
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:layout_margin="16dp"
        android:onClick="startClick"
        android:text="@string/buttonStartText" />

</LinearLayout>

================================================
FILE: EventBusPerformance/res/values/strings.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">EventBus Performance</string>
    <string name="test_eventBus">EventBus</string>
    <string name="test_eventBusEventHierarchy">Event Inheritance</string>
    <string name="test_eventBusEventIgnoreGeneratedIndex">Ignore generated index</string>
    <string name="test_otto">OttoBus</string>
    <string name="test_broadcast">Broadcast</string>
    <string name="test_localBroadcast">Local Broadcast</string>
    <string name="eventViewText">Events:</string>
    <string name="subscriberViewText">Subscribers:</string>
    <string name="buttonStartText">Start</string>

    <string-array name="spinnerTestsToRun">
        <item>Post Events</item>
        <item>Register Subscribers</item>
        <item>Register Subscribers, no unregister</item>
        <item>Register Subscribers, 1. time</item>
    </string-array>
    <string-array name="spinnerThreadModes">
        <item>POSTING</item>
        <item>MAIN</item>
        <item>MAIN_ORDERED</item>
        <item>BACKGROUND</item>
        <item>ASYNC</item>
    </string-array>

    <string name="testIsRunning">Test Is \nRunning!</string>
    <string name="buttonCancel">Cancel</string>
    <string name="buttonKillProcess">Kill Process</string>
    
</resources>

================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/Test.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf;

import android.content.Context;

import java.util.concurrent.atomic.AtomicLong;

public abstract class Test {
    protected final Context context;
    protected final TestParams params;
    public final AtomicLong eventsReceivedCount = new AtomicLong();
    protected long primaryResultMicros;
    protected int primaryResultCount;
    protected String otherTestResults;

    protected boolean canceled;

    public Test(Context context, TestParams params) {
        this.context = context;
        this.params = params;
    }

    public void cancel() {
        canceled = true;
    }

    /** prepares the test, all things which are not relevant for test results */
    public abstract void prepareTest();

    public abstract void runTest();

    /** returns the display name of the test. e.g. EventBus */
    public abstract String getDisplayName();

    protected void waitForReceivedEventCount(int expectedEventCount) {
        while (eventsReceivedCount.get() < expectedEventCount) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public long getPrimaryResultMicros() {
        return primaryResultMicros;
    }

    public double getPrimaryResultRate() {
        return primaryResultCount / (primaryResultMicros / 1000000d);
    }

    public String getOtherTestResults() {
        return otherTestResults;
    }

}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestEvent.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf;

/** Used by otto and EventBus */
public class TestEvent {

}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestFinishedEvent.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf;

public class TestFinishedEvent {

    public final Test test;
    public final boolean isLastEvent;

    public TestFinishedEvent(Test test, boolean isLastEvent) {
        this.test = test;
        this.isLastEvent = isLastEvent;
    }
}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestParams.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf;

import org.greenrobot.eventbus.ThreadMode;

import java.io.Serializable;
import java.util.ArrayList;

public class TestParams implements Serializable {
    private static final long serialVersionUID = -2739435088947740809L;

    private int eventCount;
    private int subscriberCount;
    private int publisherCount;
    private ThreadMode threadMode;
    private boolean eventInheritance;
    private boolean ignoreGeneratedIndex;
    private int testNumber;
    private ArrayList<Class<? extends Test>> testClasses;

    public int getEventCount() {
        return eventCount;
    }

    public void setEventCount(int iterations) {
        this.eventCount = iterations;
    }

    public int getSubscriberCount() {
        return subscriberCount;
    }

    public void setSubscriberCount(int subscriberCount) {
        this.subscriberCount = subscriberCount;
    }

    public int getPublisherCount() {
        return publisherCount;
    }

    public void setPublisherCount(int publisherCount) {
        this.publisherCount = publisherCount;
    }

    public ThreadMode getThreadMode() {
        return threadMode;
    }

    public void setThreadMode(ThreadMode threadMode) {
        this.threadMode = threadMode;
    }

    public boolean isEventInheritance() {
        return eventInheritance;
    }

    public void setEventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
    }

    public boolean isIgnoreGeneratedIndex() {
        return ignoreGeneratedIndex;
    }

    public void setIgnoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
    }

    public ArrayList<Class<? extends Test>> getTestClasses() {
        return testClasses;
    }

    public void setTestClasses(ArrayList<Class<? extends Test>> testClasses) {
        this.testClasses = testClasses;
    }

    public int getTestNumber() {
        return testNumber;
    }

    public void setTestNumber(int testNumber) {
        this.testNumber = testNumber;
    }

}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunner.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf;

import android.content.Context;

import org.greenrobot.eventbus.EventBus;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

/**
 * This thread initialize all selected tests and runs them through. Also the thread skips the tests, when it is canceled
 */
public class TestRunner extends Thread {
    private List<Test> tests;
    private volatile boolean canceled;
    private final EventBus controlBus;

    public TestRunner(Context context, TestParams testParams, EventBus controlBus) {
        this.controlBus = controlBus;
        tests = new ArrayList<Test>();
        for (Class<? extends Test> testClazz : testParams.getTestClasses()) {
            try {
                Constructor<?>[] constructors = testClazz.getConstructors();
                Constructor<? extends Test> constructor = testClazz.getConstructor(Context.class, TestParams.class);
                Test test = constructor.newInstance(context, testParams);
                tests.add(test);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void run() {

        int idx = 0;
        for (Test test : tests) {
            // Clean up and let the main thread calm down
            System.gc();
            try {
                Thread.sleep(300);
                System.gc();
                Thread.sleep(300);
            } catch (InterruptedException e) {
            }

            test.prepareTest();
            if (!canceled) {
                test.runTest();
            }
            if (!canceled) {
                boolean isLastEvent = idx == tests.size() - 1;
                controlBus.post(new TestFinishedEvent(test, isLastEvent));
            }
            idx++;
        }

    }

    public List<Test> getTests() {
        return tests;
    }

    public void cancel() {
        canceled = true;
        for (Test test : tests) {
            test.cancel();
        }
    }
}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf;

import android.app.Activity;
import android.os.Bundle;
import android.os.Process;
import android.text.Html;
import android.view.View;
import android.widget.TextView;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

/**
 * This activity gets the information from the activity before, sets up the test and starts the test. After it watchs
 * after that, if a test is finished. When a test is finished, the activity appends it on the textview analyse. If all
 * test are finished, it cancels the timer.
 */
public class TestRunnerActivity extends Activity {

    private TestRunner testRunner;
    private EventBus controlBus;
    private TextView textViewResult;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_runtests);
        textViewResult = findViewById(R.id.textViewResult);
        controlBus = new EventBus();
        controlBus.register(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (testRunner == null) {
            TestParams testParams = (TestParams) getIntent().getSerializableExtra("params");
            testRunner = new TestRunner(getApplicationContext(), testParams, controlBus);

            if (testParams.getTestNumber() == 1) {
                textViewResult.append("Events: " + testParams.getEventCount() + "\n");
            }
            textViewResult.append("Subscribers: " + testParams.getSubscriberCount() + "\n\n");
            testRunner.start();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(TestFinishedEvent event) {
        Test test = event.test;
        String text = "<b>" + test.getDisplayName() + "</b><br/>" + //
                test.getPrimaryResultMicros() + " micro seconds<br/>" + //
                ((int) test.getPrimaryResultRate()) + "/s<br/>";
        if (test.getOtherTestResults() != null) {
            text += test.getOtherTestResults();
        }
        text += "<br/>----------------<br/>";
        textViewResult.append(Html.fromHtml(text));
        if (event.isLastEvent) {
            findViewById(R.id.buttonCancel).setVisibility(View.GONE);
            findViewById(R.id.textViewTestRunning).setVisibility(View.GONE);
            findViewById(R.id.buttonKillProcess).setVisibility(View.VISIBLE);
        }
    }

    public void onClickCancel(View view) {
        // Cancel asap
        if (testRunner != null) {
            testRunner.cancel();
            testRunner = null;
        }
        finish();
    }

    public void onClickKillProcess(View view) {
        Process.killProcess(Process.myPid());
    }

    public void onDestroy() {
        if (testRunner != null) {
            testRunner.cancel();
        }
        controlBus.unregister(this);
        super.onDestroy();
    }
}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;

import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;

import org.greenrobot.eventbusperf.testsubject.PerfTestEventBus;
import org.greenrobot.eventbusperf.testsubject.PerfTestOtto;

public class TestSetupActivity extends Activity {

    @SuppressWarnings("rawtypes")
    static final Class[] TEST_CLASSES_EVENTBUS = {PerfTestEventBus.Post.class,//
            PerfTestEventBus.RegisterOneByOne.class,//
            PerfTestEventBus.RegisterAll.class, //
            PerfTestEventBus.RegisterFirstTime.class};

    static final Class[] TEST_CLASSES_OTTO = {PerfTestOtto.Post.class,//
            PerfTestOtto.RegisterOneByOne.class,//
            PerfTestOtto.RegisterAll.class, //
            PerfTestOtto.RegisterFirstTime.class};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setuptests);

        Spinner spinnerRun = findViewById(R.id.spinnerTestToRun);
        spinnerRun.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            public void onItemSelected(AdapterView<?> adapter, View v, int pos, long lng) {
                int eventsVisibility = pos == 0 ? View.VISIBLE : View.GONE;
                findViewById(R.id.relativeLayoutForEvents).setVisibility(eventsVisibility);
                findViewById(R.id.spinnerThread).setVisibility(eventsVisibility);
            }

            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });
    }

    public void checkEventBus(View v) {
        Spinner spinnerThread = findViewById(R.id.spinnerThread);
        CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus);
        int visibility = checkBoxEventBus.isChecked() ? View.VISIBLE : View.GONE;
        spinnerThread.setVisibility(visibility);
    }

    public void startClick(View v) {
        TestParams params = new TestParams();
        Spinner spinnerThread = findViewById(R.id.spinnerThread);
        String threadModeStr = spinnerThread.getSelectedItem().toString();
        ThreadMode threadMode = ThreadMode.valueOf(threadModeStr);
        params.setThreadMode(threadMode);

        params.setEventInheritance(((CheckBox) findViewById(R.id.checkBoxEventBusEventHierarchy)).isChecked());
        params.setIgnoreGeneratedIndex(((CheckBox) findViewById(R.id.checkBoxEventBusIgnoreGeneratedIndex)).isChecked());

        EditText editTextEvent = findViewById(R.id.editTextEvent);
        params.setEventCount(Integer.parseInt(editTextEvent.getText().toString()));

        EditText editTextSubscriber = findViewById(R.id.editTextSubscribe);
        params.setSubscriberCount(Integer.parseInt(editTextSubscriber.getText().toString()));

        Spinner spinnerTestToRun = findViewById(R.id.spinnerTestToRun);
        int testPos = spinnerTestToRun.getSelectedItemPosition();
        params.setTestNumber(testPos + 1);
        ArrayList<Class<? extends Test>> testClasses = initTestClasses(testPos);
        params.setTestClasses(testClasses);

        Intent intent = new Intent();
        intent.setClass(this, TestRunnerActivity.class);
        intent.putExtra("params", params);
        startActivity(intent);
    }

    @SuppressWarnings("unchecked")
    private ArrayList<Class<? extends Test>> initTestClasses(int testPos) {
        ArrayList<Class<? extends Test>> testClasses = new ArrayList<Class<? extends Test>>();
        // the attributes are putted in the intent (eventbus, otto, broadcast, local broadcast)
        final CheckBox checkBoxEventBus = findViewById(R.id.checkBoxEventBus);
        final CheckBox checkBoxOtto = findViewById(R.id.checkBoxOtto);
        final CheckBox checkBoxBroadcast = findViewById(R.id.checkBoxBroadcast);
        final CheckBox checkBoxLocalBroadcast = findViewById(R.id.checkBoxLocalBroadcast);
        if (checkBoxEventBus.isChecked()) {
            testClasses.add(TEST_CLASSES_EVENTBUS[testPos]);
        }
        if (checkBoxOtto.isChecked()) {
            testClasses.add(TEST_CLASSES_OTTO[testPos]);
        }
        if (checkBoxBroadcast.isChecked()) {
        }
        if (checkBoxLocalBroadcast.isChecked()) {
        }

        return testClasses;
    }
}

================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf.testsubject;

import android.content.Context;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;

import org.greenrobot.eventbusperf.MyEventBusIndex;
import org.greenrobot.eventbusperf.Test;
import org.greenrobot.eventbusperf.TestEvent;
import org.greenrobot.eventbusperf.TestParams;

public abstract class PerfTestEventBus extends Test {

    private final EventBus eventBus;
    private final ArrayList<Object> subscribers;
    private final Class<?> subscriberClass;
    private final int eventCount;
    private final int expectedEventCount;

    public PerfTestEventBus(Context context, TestParams params) {
        super(context, params);
        eventBus = EventBus.builder().eventInheritance(params.isEventInheritance()).addIndex(new MyEventBusIndex())
                .ignoreGeneratedIndex(params.isIgnoreGeneratedIndex()).build();
        subscribers = new ArrayList<Object>();
        eventCount = params.getEventCount();
        expectedEventCount = eventCount * params.getSubscriberCount();
        subscriberClass = getSubscriberClassForThreadMode();
    }

    @Override
    public void prepareTest() {
        try {
            Constructor<?> constructor = subscriberClass.getConstructor(PerfTestEventBus.class);
            for (int i = 0; i < params.getSubscriberCount(); i++) {
                Object subscriber = constructor.newInstance(this);
                subscribers.add(subscriber);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Class<?> getSubscriberClassForThreadMode() {
        switch (params.getThreadMode()) {
            case MAIN:
                return SubscribeClassEventBusMain.class;
            case MAIN_ORDERED:
                return SubscribeClassEventBusMainOrdered.class;
            case BACKGROUND:
                return SubscribeClassEventBusBackground.class;
            case ASYNC:
                return SubscriberClassEventBusAsync.class;
            case POSTING:
                return SubscribeClassEventBusDefault.class;
            default:
                throw new RuntimeException("Unknown: " + params.getThreadMode());
        }
    }

    private static String getDisplayModifier(TestParams params) {
        String inheritance = params.isEventInheritance() ? "" : ", no event inheritance";
        String ignoreIndex = params.isIgnoreGeneratedIndex() ? ", ignore index" : "";
        return inheritance + ignoreIndex;
    }


    public static class Post extends PerfTestEventBus {
        public Post(Context context, TestParams params) {
            super(context, params);
        }

        @Override
        public void prepareTest() {
            super.prepareTest();
            super.registerSubscribers();
        }

        public void runTest() {
            TestEvent event = new TestEvent();
            long timeStart = System.nanoTime();
            for (int i = 0; i < super.eventCount; i++) {
                super.eventBus.post(event);
                if (canceled) {
                    break;
                }
            }
            long timeAfterPosting = System.nanoTime();
            waitForReceivedEventCount(super.expectedEventCount);
            long timeAllReceived = System.nanoTime();

            primaryResultMicros = (timeAfterPosting - timeStart) / 1000;
            primaryResultCount = super.expectedEventCount;
            long deliveredMicros = (timeAllReceived - timeStart) / 1000;
            int deliveryRate = (int) (primaryResultCount / (deliveredMicros / 1000000d));
            otherTestResults = "Post and delivery time: " + deliveredMicros + " micros<br/>" + //
                    "Post and delivery rate: " + deliveryRate + "/s";
        }

        @Override
        public String getDisplayName() {
            return "EventBus Post Events, " + params.getThreadMode() + getDisplayModifier(params);
        }

    }

    public static class RegisterAll extends PerfTestEventBus {
        public RegisterAll(Context context, TestParams params) {
            super(context, params);
        }

        public void runTest() {
            super.registerUnregisterOneSubscribers();
            long timeNanos = super.registerSubscribers();
            primaryResultMicros = timeNanos / 1000;
            primaryResultCount = params.getSubscriberCount();
        }

        @Override
        public String getDisplayName() {
            return "EventBus Register, no unregister" + getDisplayModifier(params);
        }
    }

    public static class RegisterOneByOne extends PerfTestEventBus {
        protected Method clearCachesMethod;

        public RegisterOneByOne(Context context, TestParams params) {
            super(context, params);
        }

        public void runTest() {
            long time = 0;
            if (clearCachesMethod == null) {
                // Skip first registration unless just the first registration is tested
                super.registerUnregisterOneSubscribers();
            }
            for (Object subscriber : super.subscribers) {
                if (clearCachesMethod != null) {
                    try {
                        clearCachesMethod.invoke(null);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
                long beforeRegister = System.nanoTime();
                super.eventBus.register(subscriber);
                long afterRegister = System.nanoTime();
                long end = System.nanoTime();
                long timeMeasureOverhead = (end - afterRegister) * 2;
                long timeRegister = end - beforeRegister - timeMeasureOverhead;
                time += timeRegister;
                super.eventBus.unregister(subscriber);
                if (canceled) {
                    return;
                }
            }

            primaryResultMicros = time / 1000;
            primaryResultCount = params.getSubscriberCount();
        }

        @Override
        public String getDisplayName() {
            return "EventBus Register" + getDisplayModifier(params);
        }
    }

    public static class RegisterFirstTime extends RegisterOneByOne {

        public RegisterFirstTime(Context context, TestParams params) {
            super(context, params);
            try {
                Class<?> clazz = Class.forName("org.greenrobot.eventbus.SubscriberMethodFinder");
                clearCachesMethod = clazz.getDeclaredMethod("clearCaches");
                clearCachesMethod.setAccessible(true);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public String getDisplayName() {
            return "EventBus Register, first time"+ getDisplayModifier(params);
        }

    }

    public class SubscribeClassEventBusMain {
        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEventMainThread(TestEvent event) {
            eventsReceivedCount.incrementAndGet();
        }

        public void dummy() {
        }

        public void dummy2() {
        }

        public void dummy3() {
        }

        public void dummy4() {
        }

        public void dummy5() {
        }
    }

    public class SubscribeClassEventBusMainOrdered {
        @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
        public void onEvent(TestEvent event) {
            eventsReceivedCount.incrementAndGet();
        }

        public void dummy() {
        }

        public void dummy2() {
        }

        public void dummy3() {
        }

        public void dummy4() {
        }

        public void dummy5() {
        }
    }

    public class SubscribeClassEventBusBackground {
        @Subscribe(threadMode = ThreadMode.BACKGROUND)
        public void onEventBackgroundThread(TestEvent event) {
            eventsReceivedCount.incrementAndGet();
        }

        public void dummy() {
        }

        public void dummy2() {
        }

        public void dummy3() {
        }

        public void dummy4() {
        }

        public void dummy5() {
        }
    }

    public class SubscriberClassEventBusAsync {
        @Subscribe(threadMode = ThreadMode.ASYNC)
        public void onEventAsync(TestEvent event) {
            eventsReceivedCount.incrementAndGet();
        }

        public void dummy() {
        }

        public void dummy2() {
        }

        public void dummy3() {
        }

        public void dummy4() {
        }

        public void dummy5() {
        }
    }

    private long registerSubscribers() {
        long time = 0;
        for (Object subscriber : subscribers) {
            long timeStart = System.nanoTime();
            eventBus.register(subscriber);
            long timeEnd = System.nanoTime();
            time += timeEnd - timeStart;
            if (canceled) {
                return 0;
            }
        }
        return time;
    }

    private void registerUnregisterOneSubscribers() {
        if (!subscribers.isEmpty()) {
            Object subscriber = subscribers.get(0);
            eventBus.register(subscriber);
            eventBus.unregister(subscriber);
        }
    }

}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestOtto.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf.testsubject;

import android.app.Activity;
import android.content.Context;
import android.os.Looper;

import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import com.squareup.otto.ThreadEnforcer;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

import org.greenrobot.eventbusperf.Test;
import org.greenrobot.eventbusperf.TestEvent;
import org.greenrobot.eventbusperf.TestParams;

public abstract class PerfTestOtto extends Test {

    private final Bus eventBus;
    private final ArrayList<Object> subscribers;
    private final Class<?> subscriberClass;
    private final int eventCount;
    private final int expectedEventCount;

    public PerfTestOtto(Context context, TestParams params) {
        super(context, params);
        eventBus = new Bus(ThreadEnforcer.ANY);
        subscribers = new ArrayList<Object>();
        eventCount = params.getEventCount();
        expectedEventCount = eventCount * params.getSubscriberCount();
        subscriberClass = Subscriber.class;
    }

    @Override
    public void prepareTest() {
        Looper.prepare();

        try {
            Constructor<?> constructor = subscriberClass.getConstructor(PerfTestOtto.class);
            for (int i = 0; i < params.getSubscriberCount(); i++) {
                Object subscriber = constructor.newInstance(this);
                subscribers.add(subscriber);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static class Post extends PerfTestOtto {
        public Post(Context context, TestParams params) {
            super(context, params);
        }

        @Override
        public void prepareTest() {
            super.prepareTest();
            super.registerSubscribers();
        }

        public void runTest() {
            TestEvent event = new TestEvent();
            long timeStart = System.nanoTime();
            for (int i = 0; i < super.eventCount; i++) {
                super.eventBus.post(event);
                if (canceled) {
                    break;
                }
            }
            long timeAfterPosting = System.nanoTime();
            waitForReceivedEventCount(super.expectedEventCount);

            primaryResultMicros = (timeAfterPosting - timeStart) / 1000;
            primaryResultCount = super.expectedEventCount;
        }

        @Override
        public String getDisplayName() {
            return "Otto Post Events";
        }
    }

    public static class RegisterAll extends PerfTestOtto {
        public RegisterAll(Context context, TestParams params) {
            super(context, params);
        }

        public void runTest() {
            super.registerUnregisterOneSubscribers();
            long timeNanos = super.registerSubscribers();
            primaryResultMicros = timeNanos / 1000;
            primaryResultCount = params.getSubscriberCount();
        }

        @Override
        public String getDisplayName() {
            return "Otto Register, no unregister";
        }
    }

    public static class RegisterOneByOne extends PerfTestOtto {
        protected Field cacheField;

        public RegisterOneByOne(Context context, TestParams params) {
            super(context, params);
        }

        @SuppressWarnings("rawtypes")
        public void runTest() {
            long time = 0;
            if (cacheField == null) {
                // Skip first registration unless just the first registration is tested
                super.registerUnregisterOneSubscribers();
            }
            for (Object subscriber : super.subscribers) {
                if (cacheField != null) {
                    try {
                        cacheField.set(null, new ConcurrentHashMap());
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
                long beforeRegister = System.nanoTime();
                super.eventBus.register(subscriber);

                long afterRegister = System.nanoTime();
                long end = System.nanoTime();
                long timeMeasureOverhead = (end - afterRegister) * 2;
                long timeRegister = end - beforeRegister - timeMeasureOverhead;
                time += timeRegister;
                super.eventBus.unregister(subscriber);
                if (canceled) {
                    return;
                }
            }

            primaryResultMicros = time / 1000;
            primaryResultCount = params.getSubscriberCount();
        }

        @Override
        public String getDisplayName() {
            return "Otto Register";
        }
    }

    public static class RegisterFirstTime extends RegisterOneByOne {

        public RegisterFirstTime(Context context, TestParams params) {
            super(context, params);
            try {
                Class<?> clazz = Class.forName("com.squareup.otto.AnnotatedHandlerFinder");
                cacheField = clazz.getDeclaredField("SUBSCRIBERS_CACHE");
                cacheField.setAccessible(true);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public String getDisplayName() {
            return "Otto Register, first time";
        }

    }

    public class Subscriber extends Activity {
        public Subscriber() {
        }

        @Subscribe
        public void onEvent(TestEvent event) {
            eventsReceivedCount.incrementAndGet();
        }

        public void dummy() {
        }

        public void dummy2() {
        }

        public void dummy3() {
        }

        public void dummy4() {
        }

        public void dummy5() {
        }

    }

    private long registerSubscribers() {
        long time = 0;
        for (Object subscriber : subscribers) {
            long timeStart = System.nanoTime();
            eventBus.register(subscriber);
            long timeEnd = System.nanoTime();
            time += timeEnd - timeStart;
            if (canceled) {
                return 0;
            }
        }
        return time;
    }

    private void registerUnregisterOneSubscribers() {
        if (!subscribers.isEmpty()) {
            Object subscriber = subscribers.get(0);
            eventBus.register(subscriber);
            eventBus.unregister(subscriber);
        }
    }

}


================================================
FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/SubscribeClassEventBusDefault.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbusperf.testsubject;

import org.greenrobot.eventbus.Subscribe;

import org.greenrobot.eventbusperf.TestEvent;

public class SubscribeClassEventBusDefault {
    private PerfTestEventBus perfTestEventBus;

    public SubscribeClassEventBusDefault(PerfTestEventBus perfTestEventBus) {
        this.perfTestEventBus = perfTestEventBus;
    }

    @Subscribe
    public void onEvent(TestEvent event) {
        perfTestEventBus.eventsReceivedCount.incrementAndGet();
    }

    public void dummy() {
    }

    public void dummy2() {
    }

    public void dummy3() {
    }

    public void dummy4() {
    }

    public void dummy5() {
    }
}


================================================
FILE: EventBusTest/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="org.greenrobot.eventbus">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="false"
        android:label="EventBus Test"
        tools:ignore="GoogleAppIndexingWarning,MissingApplicationIcon">
    </application>

</manifest>

================================================
FILE: EventBusTest/build.gradle
================================================
buildscript {
    repositories {
        google()
        mavenCentral()
    }

    dependencies {
        // Note: IntelliJ IDEA 2021.1 only supports up to version 4.1
        classpath 'com.android.tools.build:gradle:4.1.3'
    }
}

apply plugin: 'com.android.application'

dependencies {
    androidTestImplementation project(':eventbus-android')
    androidTestImplementation project(':EventBusTestJava')
    androidTestAnnotationProcessor project(':eventbus-annotation-processor')
    // Trying to repro bug:
//    androidTestAnnotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.0'
    implementation fileTree(dir: 'libs', include: '*.jar')
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
}

android {
    compileSdkVersion _compileSdkVersion

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_7
        targetCompatibility = JavaVersion.VERSION_1_7
    }

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
        }

        androidTest {
            java.srcDirs = ['src']
        }
    }

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

        testApplicationId "de.greenrobot.event.test"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ eventBusIndex : 'org.greenrobot.eventbus.EventBusTestsIndex' ]
            }
        }
    }

    useLibrary 'android.test.base'

    lintOptions {
        // To see problems right away, also nice for Travis CI
        textOutput 'stdout'

        // TODO FIXME: Travis only error
        abortOnError false
    }
}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.runner.RunWith;


import static org.junit.Assert.assertFalse;

/**
 * @author Markus Junginger, greenrobot
 */
@RunWith(AndroidJUnit4.class)
public abstract class AbstractAndroidEventBusTest extends AbstractEventBusTest {
    private EventPostHandler mainPoster;

    public AbstractAndroidEventBusTest() {
        this(false);
    }

    public AbstractAndroidEventBusTest(boolean collectEventsReceived) {
        super(collectEventsReceived);
    }

    @Before
    public void setUpAndroid() throws Exception {
        mainPoster = new EventPostHandler(Looper.getMainLooper());
        assertFalse(Looper.getMainLooper().getThread().equals(Thread.currentThread()));
    }

    protected void postInMainThread(Object event) {
        mainPoster.post(event);
    }

    @SuppressLint("HandlerLeak")
    class EventPostHandler extends Handler {
        public EventPostHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            eventBus.post(msg.obj);
        }

        void post(Object event) {
            sendMessage(obtainMessage(0, event));
        }

    }

}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java
================================================
package org.greenrobot.eventbus;

import org.greenrobot.eventbus.android.AndroidComponents;
import org.junit.Test;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class AndroidComponentsAvailabilityTest {

    @Test
    public void shouldBeAvailable() {
        assertTrue(AndroidComponents.areAvailable());
        assertNotNull(AndroidComponents.get());
    }
}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/ClassMapPerfTest.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbus;

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * Just to verify testHashMapClassObject is fastest. Ignore this test.
 */
public class ClassMapPerfTest /* extends TestCase */ {

    static final int COUNT = 10000000;
    static final Class CLAZZ = ClassMapPerfTest.class;

    public void testHashMapClassObject() {
        Map<Class, Class> map = new HashMap<Class, Class>();
        for (int i = 0; i < COUNT; i++) {
            Class oldValue = map.put(CLAZZ, CLAZZ);
            Class value = map.get(CLAZZ);
        }
    }

    public void testIdentityHashMapClassObject() {
        Map<Class, Class> map = new IdentityHashMap<Class, Class>();
        for (int i = 0; i < COUNT; i++) {
            Class oldValue = map.put(CLAZZ, CLAZZ);
            Class value = map.get(CLAZZ);
        }
    }

    public void testHashMapClassName() {
        Map<String, Class> map = new HashMap<String, Class>();
        for (int i = 0; i < COUNT; i++) {
            Class oldValue = map.put(CLAZZ.getName(), CLAZZ);
            Class value = map.get(CLAZZ.getName());
        }
    }

}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import android.app.Activity;
import android.support.test.annotation.UiThreadTest;
import android.support.test.rule.UiThreadTestRule;
import android.util.Log;

import org.junit.Rule;
import org.junit.Test;


import static org.junit.Assert.assertEquals;

/**
 * @author Markus Junginger, greenrobot
 */
// Do not extend from AbstractAndroidEventBusTest, because it asserts test may not be in main thread
public class EventBusAndroidActivityTest extends AbstractEventBusTest {

    public static class WithIndex extends EventBusBasicTest {
        @Test
        public void dummy() {
        }

    }

    @Rule
    public final UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();

    @Test
    @UiThreadTest
    public void testRegisterAndPost() {
        // Use an activity to test real life performance
        TestActivity testActivity = new TestActivity();
        String event = "Hello";

        long start = System.currentTimeMillis();
        eventBus.register(testActivity);
        long time = System.currentTimeMillis() - start;
        Log.d(EventBus.TAG, "Registered in " + time + "ms");

        eventBus.post(event);

        assertEquals(event, testActivity.lastStringEvent);
    }

    public static class TestActivity extends Activity {
        public String lastStringEvent;

        @Subscribe
        public void onEvent(String event) {
            lastStringEvent = event;
        }
    }

}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import org.junit.Test;
import org.junit.runner.RunWith;

import android.support.test.runner.AndroidJUnit4;
import android.test.UiThreadTest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@RunWith(AndroidJUnit4.class)
public class EventBusAndroidCancelEventDeliveryTest extends EventBusCancelEventDeliveryTest {

    @UiThreadTest
    @Test
    public void testCancelInMainThread() {
        SubscriberMainThread subscriber = new SubscriberMainThread();
        eventBus.register(subscriber);
        eventBus.post("42");
        awaitLatch(subscriber.done, 10);
        assertEquals(0, eventCount.intValue());
        assertNotNull(failed);
    }

}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import org.junit.Test;
import org.junit.runner.RunWith;

import android.os.Looper;
import android.support.test.runner.AndroidJUnit4;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;

@RunWith(AndroidJUnit4.class)
public class EventBusAndroidMultithreadedTest extends EventBusMultithreadedTest {

    @Test
    public void testSubscribeUnSubscribeAndPostMixedEventType() throws InterruptedException {
        List<SubscribeUnsubscribeThread> threads = new ArrayList<SubscribeUnsubscribeThread>();

        // Debug.startMethodTracing("testSubscribeUnSubscribeAndPostMixedEventType");
        for (int i = 0; i < 5; i++) {
            SubscribeUnsubscribeThread thread = new SubscribeUnsubscribeThread();
            thread.start();
            threads.add(thread);
        }
        // This test takes a bit longer, so just use fraction the regular count
        runThreadsMixedEventType(COUNT / 4, 5);
        for (SubscribeUnsubscribeThread thread : threads) {
            thread.shutdown();
        }
        for (SubscribeUnsubscribeThread thread : threads) {
            thread.join();
        }
        // Debug.stopMethodTracing();
    }

    public class SubscribeUnsubscribeThread extends Thread {
        boolean running = true;

        public void shutdown() {
            running = false;
        }

        @Override
        public void run() {
            try {
                while (running) {
                    eventBus.register(this);
                    double random = Math.random();
                    if (random > 0.6d) {
                        Thread.sleep(0, (int) (1000000 * Math.random()));
                    } else if (random > 0.3d) {
                        Thread.yield();
                    }
                    eventBus.unregister(this);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onEventMainThread(String event) {
            assertSame(Looper.getMainLooper(), Looper.myLooper());
        }

        @Subscribe(threadMode = ThreadMode.BACKGROUND)
        public void onEventBackgroundThread(Integer event) {
            assertNotSame(Looper.getMainLooper(), Looper.myLooper());
        }

        @Subscribe
        public void onEvent(Object event) {
            assertNotSame(Looper.getMainLooper(), Looper.myLooper());
        }

        @Subscribe(threadMode = ThreadMode.ASYNC)
        public void onEventAsync(Object event) {
            assertNotSame(Looper.getMainLooper(), Looper.myLooper());
        }
    }

}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java
================================================
package org.greenrobot.eventbus;

import android.os.Handler;
import android.os.Looper;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;


import static org.junit.Assert.assertEquals;

public class EventBusAndroidOrderTest extends AbstractAndroidEventBusTest {

    private TestBackgroundPoster backgroundPoster;
    private Handler handler;

    @Before
    public void setUp() throws Exception {
        handler = new Handler(Looper.getMainLooper());
        backgroundPoster = new TestBackgroundPoster(eventBus);
        backgroundPoster.start();
    }

    @After
    public void tearDown() throws Exception {
        backgroundPoster.shutdown();
        backgroundPoster.join();
    }

    @Test
    public void backgroundAndMainUnordered() {
        eventBus.register(this);

        handler.post(new Runnable() {
            @Override
            public void run() {
                // post from non-main thread
                backgroundPoster.post("non-main");
                // post from main thread
                eventBus.post("main");
            }
        });

        waitForEventCount(2, 1000);

        // observe that event from *main* thread is posted FIRST
        // NOT in posting order
        assertEquals("non-main", lastEvent);
    }

    @Test
    public void backgroundAndMainOrdered() {
        eventBus.register(this);

        handler.post(new Runnable() {
            @Override
            public void run() {
                // post from non-main thread
                backgroundPoster.post(new OrderedEvent("non-main"));
                // post from main thread
                eventBus.post(new OrderedEvent("main"));
            }
        });

        waitForEventCount(2, 1000);

        // observe that event from *main* thread is posted LAST
        // IN posting order
        assertEquals("main", ((OrderedEvent) lastEvent).thread);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(String event) {
        trackEvent(event);
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void onEvent(OrderedEvent event) {
        trackEvent(event);
    }

    static class OrderedEvent {
        String thread;

        OrderedEvent(String thread) {
            this.thread = thread;
        }
    }

}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import android.os.Looper;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

/**
 * @author Markus Junginger, greenrobot
 */
public class EventBusBackgroundThreadTest extends AbstractAndroidEventBusTest {

    @Test
    public void testPostInCurrentThread() throws InterruptedException {
        eventBus.register(this);
        eventBus.post("Hello");
        waitForEventCount(1, 1000);

        assertEquals("Hello", lastEvent);
        assertEquals(Thread.currentThread(), lastThread);
    }

    @Test
    public void testPostFromMain() throws InterruptedException {
        eventBus.register(this);
        postInMainThread("Hello");
        waitForEventCount(1, 1000);
        assertEquals("Hello", lastEvent);
        assertFalse(lastThread.equals(Thread.currentThread()));
        assertFalse(lastThread.equals(Looper.getMainLooper().getThread()));
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onEventBackgroundThread(String event) {
        trackEvent(event);
    }

}


================================================
FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java
================================================
/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import android.os.Handler;
import android.os.Looper;

import org.junit.Test;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

/**
 * @author Markus Junginger, greenrobot
 */
public class EventBusMainThreadRacingTest extends AbstractAndroidEventBusTest {

    private static final int ITERATIONS = LONG_TESTS ? 100000 : 1000;

    protected boolean unregistered;
    private CountDownLatch startLatch;
    private volatile RuntimeException failed;

    @Test
    public void testRacingThreads() throws InterruptedException {
        Runnable register = new Runnable() {
            @Override
            public void run() {
                eventBus.register(EventBusMainThreadRacingTest.this);
                unregistered = false;
            }
        };

        Runnable unregister = new Runnable() {
            @Override
            public void run() {
                eventBus.unregister(EventBusMainThreadRacingTest.this);
                unregistered = true;
            }
        };

        startLatch = new CountDownLatch(2);
        BackgroundPoster backgroundPoster = new BackgroundPoster();
        backgroundPoster.start();
        try {
            Handler handler = new Handler(Looper.getMainLooper());
            Random random = new Random();
            countDownAndAwaitLatch(startLatch, 10);
            for (int i = 0; i < ITERATIONS; i++) {
                handler.post(register);
                Thread.sleep(0, random.nextInt(300)); // Sleep just some nanoseconds, timing is crucial here
                handler.post(unregister);
                if (failed != null) {
                    throw new RuntimeException("Failed in iteration " + i, failed);
                }
                // Don't let the queue grow to avoid out-of-memory scenarios
                waitForHandler(handler);
            }
        } finally {
            backgroundPoster.running = false;
            backgroundPoster.join();
        }
    }

    protected void waitForHandler(Handler handler) {
        final CountDownLatch doneLatch = new CountDownLatch(1);
        handler.post(new Runnable() {

            @Override
            public void run() {
                doneLatch.countDown();
            }
        });
        awaitLatch(doneLatch, 10);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(String event) {
        trackEvent(event);
        if (unregistered) {
       
Download .txt
gitextract_vwo4kya5/

├── .github/
│   └── workflows/
│       └── gradle.yml
├── .gitignore
├── COMPARISON.md
├── CONTRIBUTING.md
├── EventBus/
│   ├── build.gradle
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   ├── AsyncPoster.java
│                   ├── BackgroundPoster.java
│                   ├── EventBus.java
│                   ├── EventBusBuilder.java
│                   ├── EventBusException.java
│                   ├── Logger.java
│                   ├── MainThreadSupport.java
│                   ├── NoSubscriberEvent.java
│                   ├── PendingPost.java
│                   ├── PendingPostQueue.java
│                   ├── Poster.java
│                   ├── Subscribe.java
│                   ├── SubscriberExceptionEvent.java
│                   ├── SubscriberMethod.java
│                   ├── SubscriberMethodFinder.java
│                   ├── Subscription.java
│                   ├── ThreadMode.java
│                   ├── android/
│                   │   ├── AndroidComponents.java
│                   │   └── AndroidDependenciesDetector.java
│                   ├── meta/
│                   │   ├── AbstractSubscriberInfo.java
│                   │   ├── SimpleSubscriberInfo.java
│                   │   ├── SubscriberInfo.java
│                   │   ├── SubscriberInfoIndex.java
│                   │   └── SubscriberMethodInfo.java
│                   └── util/
│                       ├── AsyncExecutor.java
│                       ├── ExceptionToResourceMapping.java
│                       ├── HasExecutionScope.java
│                       └── ThrowableFailureEvent.java
├── EventBusAnnotationProcessor/
│   ├── build.gradle
│   ├── res/
│   │   └── META-INF/
│   │       └── services/
│   │           └── javax.annotation.processing.Processor
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   └── annotationprocessor/
│                       └── EventBusAnnotationProcessor.java
├── EventBusPerformance/
│   ├── .gitignore
│   ├── AndroidManifest.xml
│   ├── build.gradle
│   ├── proguard-project.txt
│   ├── project.properties
│   ├── res/
│   │   ├── layout/
│   │   │   ├── activity_runtests.xml
│   │   │   └── activity_setuptests.xml
│   │   └── values/
│   │       └── strings.xml
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbusperf/
│                   ├── Test.java
│                   ├── TestEvent.java
│                   ├── TestFinishedEvent.java
│                   ├── TestParams.java
│                   ├── TestRunner.java
│                   ├── TestRunnerActivity.java
│                   ├── TestSetupActivity.java
│                   └── testsubject/
│                       ├── PerfTestEventBus.java
│                       ├── PerfTestOtto.java
│                       └── SubscribeClassEventBusDefault.java
├── EventBusTest/
│   ├── AndroidManifest.xml
│   ├── build.gradle
│   ├── libs/
│   │   └── EventBusTestSubscriberInJar-3.0.0.jar
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   ├── AbstractAndroidEventBusTest.java
│                   ├── AndroidComponentsAvailabilityTest.java
│                   ├── ClassMapPerfTest.java
│                   ├── EventBusAndroidActivityTest.java
│                   ├── EventBusAndroidCancelEventDeliveryTest.java
│                   ├── EventBusAndroidMultithreadedTest.java
│                   ├── EventBusAndroidOrderTest.java
│                   ├── EventBusBackgroundThreadTest.java
│                   ├── EventBusMainThreadRacingTest.java
│                   ├── EventBusMainThreadTest.java
│                   ├── EventBusMethodModifiersTest.java
│                   ├── TestBackgroundPoster.java
│                   └── indexed/
│                       ├── EventBusAndroidOrderTestWithIndex.java
│                       ├── EventBusBackgroundThreadTestWithIndex.java
│                       ├── EventBusBasicTestWithIndex.java
│                       ├── EventBusCancelEventDeliveryTestWithIndex.java
│                       ├── EventBusFallbackToReflectionTestWithIndex.java
│                       ├── EventBusGenericsTestWithIndex.java
│                       ├── EventBusInheritanceDisabledTestWithIndex.java
│                       ├── EventBusInheritanceTestWithIndex.java
│                       ├── EventBusMainThreadRacingTestWithIndex.java
│                       ├── EventBusMainThreadTestWithIndex.java
│                       ├── EventBusMethodModifiersTestWithIndex.java
│                       ├── EventBusMultithreadedTestWithIndex.java
│                       ├── EventBusNoSubscriberEventTestWithIndex.java
│                       ├── EventBusOrderedSubscriptionsTestWithIndex.java
│                       ├── EventBusRegistrationRacingTestWithIndex.java
│                       ├── EventBusStickyEventTestWithIndex.java
│                       ├── EventBusSubscriberExceptionTestWithIndex.java
│                       ├── EventBusSubscriberInJarTestWithIndex.java
│                       └── Indexed.java
├── EventBusTestJava/
│   ├── build.gradle
│   ├── libs/
│   │   └── EventBusTestSubscriberInJar-3.0.0.jar
│   └── src/
│       └── main/
│           └── java/
│               └── org/
│                   └── greenrobot/
│                       └── eventbus/
│                           ├── AbstractEventBusTest.java
│                           ├── EventBusBasicTest.java
│                           ├── EventBusBuilderTest.java
│                           ├── EventBusCancelEventDeliveryTest.java
│                           ├── EventBusFallbackToReflectionTest.java
│                           ├── EventBusGenericsTest.java
│                           ├── EventBusIndexTest.java
│                           ├── EventBusInheritanceDisabledSubclassNoMethod.java
│                           ├── EventBusInheritanceDisabledSubclassTest.java
│                           ├── EventBusInheritanceDisabledTest.java
│                           ├── EventBusInheritanceSubclassNoMethodTest.java
│                           ├── EventBusInheritanceSubclassTest.java
│                           ├── EventBusInheritanceTest.java
│                           ├── EventBusMultithreadedTest.java
│                           ├── EventBusNoSubscriberEventTest.java
│                           ├── EventBusOrderedSubscriptionsTest.java
│                           ├── EventBusRegistrationRacingTest.java
│                           ├── EventBusStickyEventTest.java
│                           ├── EventBusSubscriberExceptionTest.java
│                           ├── EventBusSubscriberInJarTest.java
│                           ├── EventBusSubscriberLegalTest.java
│                           └── IntTestEvent.java
├── EventBusTestSubscriberInJar/
│   ├── build.gradle
│   └── src/
│       └── org/
│           └── greenrobot/
│               └── eventbus/
│                   └── SubscriberInJar.java
├── LICENSE
├── README.md
├── build.gradle
├── eventbus-android/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── org/
│                   └── greenrobot/
│                       └── eventbus/
│                           ├── HandlerPoster.java
│                           └── android/
│                               ├── AndroidComponentsImpl.java
│                               ├── AndroidLogger.java
│                               └── DefaultAndroidMainThreadSupport.java
├── gradle/
│   ├── publish.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── javadoc-style/
│   └── stylesheet.css
└── settings.gradle
Download .txt
SYMBOL INDEX (735 symbols across 96 files)

FILE: EventBus/src/org/greenrobot/eventbus/AsyncPoster.java
  class AsyncPoster (line 24) | class AsyncPoster implements Runnable, Poster {
    method AsyncPoster (line 29) | AsyncPoster(EventBus eventBus) {
    method enqueue (line 34) | public void enqueue(Subscription subscription, Object event) {
    method run (line 40) | @Override

FILE: EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java
  class BackgroundPoster (line 25) | final class BackgroundPoster implements Runnable, Poster {
    method BackgroundPoster (line 32) | BackgroundPoster(EventBus eventBus) {
    method enqueue (line 37) | public void enqueue(Subscription subscription, Object event) {
    method run (line 48) | @Override

FILE: EventBus/src/org/greenrobot/eventbus/EventBus.java
  class EventBus (line 41) | public class EventBus {
    method initialValue (line 56) | @Override
    method getDefault (line 82) | public static EventBus getDefault() {
    method builder (line 95) | public static EventBusBuilder builder() {
    method clearCaches (line 100) | public static void clearCaches() {
    method EventBus (line 109) | public EventBus() {
    method EventBus (line 113) | EventBus(EventBusBuilder builder) {
    method register (line 142) | public void register(Object subscriber) {
    method subscribe (line 159) | private void subscribe(Object subscriber, SubscriberMethod subscriberM...
    method checkPostStickyEventToSubscription (line 209) | private void checkPostStickyEventToSubscription(Subscription newSubscr...
    method isMainThread (line 223) | private boolean isMainThread() {
    method isRegistered (line 227) | public synchronized boolean isRegistered(Object subscriber) {
    method unsubscribeByEventType (line 232) | private void unsubscribeByEventType(Object subscriber, Class<?> eventT...
    method unregister (line 249) | public synchronized void unregister(Object subscriber) {
    method post (line 262) | public void post(Object event) {
    method cancelEventDelivery (line 291) | public void cancelEventDelivery(Object event) {
    method postSticky (line 311) | public void postSticky(Object event) {
    method getStickyEvent (line 324) | public <T> T getStickyEvent(Class<T> eventType) {
    method removeStickyEvent (line 335) | public <T> T removeStickyEvent(Class<T> eventType) {
    method removeStickyEvent (line 346) | public boolean removeStickyEvent(Object event) {
    method removeAllStickyEvents (line 362) | public void removeAllStickyEvents() {
    method hasSubscriberForEvent (line 368) | public boolean hasSubscriberForEvent(Class<?> eventClass) {
    method postSingleEvent (line 386) | private void postSingleEvent(Object event, PostingThreadState postingS...
    method postSingleEventForEventType (line 410) | private boolean postSingleEventForEventType(Object event, PostingThrea...
    method postToSubscription (line 437) | private void postToSubscription(Subscription subscription, Object even...
    method lookupAllEventTypes (line 473) | private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
    method addInterfaces (line 491) | static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interf...
    method invokeSubscriber (line 506) | void invokeSubscriber(PendingPost pendingPost) {
    method invokeSubscriber (line 515) | void invokeSubscriber(Subscription subscription, Object event) {
    method handleSubscriberException (line 525) | private void handleSubscriberException(Subscription subscription, Obje...
    class PostingThreadState (line 552) | final static class PostingThreadState {
    method getExecutorService (line 561) | ExecutorService getExecutorService() {
    method getLogger (line 568) | public Logger getLogger() {
    type PostCallback (line 573) | interface PostCallback {
      method onPostCompleted (line 574) | void onPostCompleted(List<SubscriberExceptionEvent> exceptionEvents);
    method toString (line 577) | @Override

FILE: EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java
  class EventBusBuilder (line 29) | @SuppressWarnings("unused")
    method EventBusBuilder (line 47) | EventBusBuilder() {
    method logSubscriberExceptions (line 51) | public EventBusBuilder logSubscriberExceptions(boolean logSubscriberEx...
    method logNoSubscriberMessages (line 57) | public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriber...
    method sendSubscriberExceptionEvent (line 63) | public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscr...
    method sendNoSubscriberEvent (line 69) | public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberE...
    method throwSubscriberException (line 80) | public EventBusBuilder throwSubscriberException(boolean throwSubscribe...
    method eventInheritance (line 94) | public EventBusBuilder eventInheritance(boolean eventInheritance) {
    method executorService (line 104) | public EventBusBuilder executorService(ExecutorService executorService) {
    method skipMethodVerificationFor (line 114) | public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
    method ignoreGeneratedIndex (line 123) | public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedInd...
    method strictMethodVerification (line 129) | public EventBusBuilder strictMethodVerification(boolean strictMethodVe...
    method addIndex (line 135) | public EventBusBuilder addIndex(SubscriberInfoIndex index) {
    method logger (line 148) | public EventBusBuilder logger(Logger logger) {
    method getLogger (line 153) | Logger getLogger() {
    method getMainThreadSupport (line 161) | MainThreadSupport getMainThreadSupport() {
    method installDefaultEventBus (line 177) | public EventBus installDefaultEventBus() {
    method build (line 189) | public EventBus build() {

FILE: EventBus/src/org/greenrobot/eventbus/EventBusException.java
  class EventBusException (line 24) | public class EventBusException extends RuntimeException {
    method EventBusException (line 28) | public EventBusException(String detailMessage) {
    method EventBusException (line 32) | public EventBusException(Throwable throwable) {
    method EventBusException (line 36) | public EventBusException(String detailMessage, Throwable throwable) {

FILE: EventBus/src/org/greenrobot/eventbus/Logger.java
  type Logger (line 21) | public interface Logger {
    method log (line 23) | void log(Level level, String msg);
    method log (line 25) | void log(Level level, String msg, Throwable th);
    class JavaLogger (line 27) | class JavaLogger implements Logger {
      method JavaLogger (line 30) | public JavaLogger(String tag) {
      method log (line 34) | @Override
      method log (line 40) | @Override
    class SystemOutLogger (line 48) | class SystemOutLogger implements Logger {
      method log (line 50) | @Override
      method log (line 55) | @Override
    class Default (line 63) | class Default {
      method get (line 64) | public static Logger get() {

FILE: EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java
  type MainThreadSupport (line 21) | public interface MainThreadSupport {
    method isMainThread (line 23) | boolean isMainThread();
    method createPoster (line 25) | Poster createPoster(EventBus eventBus);

FILE: EventBus/src/org/greenrobot/eventbus/NoSubscriberEvent.java
  class NoSubscriberEvent (line 23) | public final class NoSubscriberEvent {
    method NoSubscriberEvent (line 30) | public NoSubscriberEvent(EventBus eventBus, Object originalEvent) {

FILE: EventBus/src/org/greenrobot/eventbus/PendingPost.java
  class PendingPost (line 21) | final class PendingPost {
    method PendingPost (line 28) | private PendingPost(Object event, Subscription subscription) {
    method obtainPendingPost (line 33) | static PendingPost obtainPendingPost(Subscription subscription, Object...
    method releasePendingPost (line 47) | static void releasePendingPost(PendingPost pendingPost) {

FILE: EventBus/src/org/greenrobot/eventbus/PendingPostQueue.java
  class PendingPostQueue (line 19) | final class PendingPostQueue {
    method enqueue (line 23) | synchronized void enqueue(PendingPost pendingPost) {
    method poll (line 38) | synchronized PendingPost poll() {
    method poll (line 49) | synchronized PendingPost poll(int maxMillisToWait) throws InterruptedE...

FILE: EventBus/src/org/greenrobot/eventbus/Poster.java
  type Poster (line 23) | public interface Poster {
    method enqueue (line 31) | void enqueue(Subscription subscription, Object event);

FILE: EventBus/src/org/greenrobot/eventbus/SubscriberExceptionEvent.java
  class SubscriberExceptionEvent (line 23) | public final class SubscriberExceptionEvent {
    method SubscriberExceptionEvent (line 36) | public SubscriberExceptionEvent(EventBus eventBus, Throwable throwable...

FILE: EventBus/src/org/greenrobot/eventbus/SubscriberMethod.java
  class SubscriberMethod (line 21) | public class SubscriberMethod {
    method SubscriberMethod (line 30) | public SubscriberMethod(Method method, Class<?> eventType, ThreadMode ...
    method equals (line 38) | @Override
    method checkMethodString (line 53) | private synchronized void checkMethodString() {
    method hashCode (line 64) | @Override

FILE: EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java
  class SubscriberMethodFinder (line 29) | class SubscriberMethodFinder {
    method SubscriberMethodFinder (line 48) | SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes...
    method findSubscriberMethods (line 55) | List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    method findUsingInfo (line 75) | private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    method getMethodsAndRelease (line 95) | private List<SubscriberMethod> getMethodsAndRelease(FindState findStat...
    method prepareFindState (line 109) | private FindState prepareFindState() {
    method getSubscriberInfo (line 122) | private SubscriberInfo getSubscriberInfo(FindState findState) {
    method findUsingReflection (line 140) | private List<SubscriberMethod> findUsingReflection(Class<?> subscriber...
    method findUsingReflectionInSingleClass (line 150) | private void findUsingReflectionInSingleClass(FindState findState) {
    method clearCaches (line 197) | static void clearCaches() {
    class FindState (line 201) | static class FindState {
      method initForSubscriber (line 212) | void initForSubscriber(Class<?> subscriberClass) {
      method recycle (line 218) | void recycle() {
      method checkAdd (line 229) | boolean checkAdd(Method method, Class<?> eventType) {
      method checkAddWithMethodSignature (line 248) | private boolean checkAddWithMethodSignature(Method method, Class<?> ...
      method moveToSuperclass (line 266) | void moveToSuperclass() {

FILE: EventBus/src/org/greenrobot/eventbus/Subscription.java
  class Subscription (line 18) | final class Subscription {
    method Subscription (line 27) | Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
    method equals (line 33) | @Override
    method hashCode (line 44) | @Override

FILE: EventBus/src/org/greenrobot/eventbus/ThreadMode.java
  type ThreadMode (line 24) | public enum ThreadMode {

FILE: EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java
  class AndroidComponents (line 6) | public abstract class AndroidComponents {
    method areAvailable (line 16) | public static boolean areAvailable() {
    method get (line 20) | public static AndroidComponents get() {
    method AndroidComponents (line 27) | public AndroidComponents(Logger logger, MainThreadSupport defaultMainT...

FILE: EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java
  class AndroidDependenciesDetector (line 6) | @SuppressWarnings("TryWithIdenticalCatches")
    method isAndroidSDKAvailable (line 9) | public static boolean isAndroidSDKAvailable() {
    method areAndroidComponentsAvailable (line 27) | public static boolean areAndroidComponentsAvailable() {
    method instantiateAndroidComponents (line 38) | public static AndroidComponents instantiateAndroidComponents() {

FILE: EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java
  class AbstractSubscriberInfo (line 25) | public abstract class AbstractSubscriberInfo implements SubscriberInfo {
    method AbstractSubscriberInfo (line 30) | protected AbstractSubscriberInfo(Class subscriberClass, Class<? extend...
    method getSubscriberClass (line 37) | @Override
    method getSuperSubscriberInfo (line 42) | @Override
    method shouldCheckSuperclass (line 56) | @Override
    method createSubscriberMethod (line 61) | protected SubscriberMethod createSubscriberMethod(String methodName, C...
    method createSubscriberMethod (line 65) | protected SubscriberMethod createSubscriberMethod(String methodName, C...
    method createSubscriberMethod (line 69) | protected SubscriberMethod createSubscriberMethod(String methodName, C...

FILE: EventBus/src/org/greenrobot/eventbus/meta/SimpleSubscriberInfo.java
  class SimpleSubscriberInfo (line 23) | public class SimpleSubscriberInfo extends AbstractSubscriberInfo {
    method SimpleSubscriberInfo (line 27) | public SimpleSubscriberInfo(Class subscriberClass, boolean shouldCheck...
    method getSubscriberMethods (line 32) | @Override

FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfo.java
  type SubscriberInfo (line 21) | public interface SubscriberInfo {
    method getSubscriberClass (line 22) | Class<?> getSubscriberClass();
    method getSubscriberMethods (line 24) | SubscriberMethod[] getSubscriberMethods();
    method getSuperSubscriberInfo (line 26) | SubscriberInfo getSuperSubscriberInfo();
    method shouldCheckSuperclass (line 28) | boolean shouldCheckSuperclass();

FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfoIndex.java
  type SubscriberInfoIndex (line 21) | public interface SubscriberInfoIndex {
    method getSubscriberInfo (line 22) | SubscriberInfo getSubscriberInfo(Class<?> subscriberClass);

FILE: EventBus/src/org/greenrobot/eventbus/meta/SubscriberMethodInfo.java
  class SubscriberMethodInfo (line 20) | public class SubscriberMethodInfo {
    method SubscriberMethodInfo (line 27) | public SubscriberMethodInfo(String methodName, Class<?> eventType, Thr...
    method SubscriberMethodInfo (line 36) | public SubscriberMethodInfo(String methodName, Class<?> eventType) {
    method SubscriberMethodInfo (line 40) | public SubscriberMethodInfo(String methodName, Class<?> eventType, Thr...

FILE: EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java
  class AsyncExecutor (line 39) | public class AsyncExecutor {
    class Builder (line 41) | public static class Builder {
      method Builder (line 46) | private Builder() {
      method threadPool (line 49) | public Builder threadPool(Executor threadPool) {
      method failureEventType (line 54) | public Builder failureEventType(Class<?> failureEventType) {
      method eventBus (line 59) | public Builder eventBus(EventBus eventBus) {
      method build (line 64) | public AsyncExecutor build() {
      method buildForScope (line 68) | public AsyncExecutor buildForScope(Object executionContext) {
    type RunnableEx (line 83) | public interface RunnableEx {
      method run (line 84) | void run() throws Exception;
    method builder (line 87) | public static Builder builder() {
    method create (line 91) | public static AsyncExecutor create() {
    method AsyncExecutor (line 100) | private AsyncExecutor(Executor threadPool, EventBus eventBus, Class<?>...
    method execute (line 113) | public void execute(final RunnableEx runnable) {

FILE: EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java
  class ExceptionToResourceMapping (line 33) | public class ExceptionToResourceMapping {
    method ExceptionToResourceMapping (line 37) | public ExceptionToResourceMapping() {
    method mapThrowable (line 42) | public Integer mapThrowable(final Throwable throwable) {
    method mapThrowableFlat (line 65) | protected Integer mapThrowableFlat(Throwable throwable) {
    method addMapping (line 85) | public ExceptionToResourceMapping addMapping(Class<? extends Throwable...

FILE: EventBus/src/org/greenrobot/eventbus/util/HasExecutionScope.java
  type HasExecutionScope (line 19) | public interface HasExecutionScope {
    method getExecutionScope (line 20) | Object getExecutionScope();
    method setExecutionScope (line 22) | void setExecutionScope(Object executionScope);

FILE: EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java
  class ThrowableFailureEvent (line 22) | public class ThrowableFailureEvent implements HasExecutionScope {
    method ThrowableFailureEvent (line 27) | public ThrowableFailureEvent(Throwable throwable) {
    method ThrowableFailureEvent (line 36) | public ThrowableFailureEvent(Throwable throwable, boolean suppressErro...
    method getThrowable (line 41) | public Throwable getThrowable() {
    method isSuppressErrorUi (line 45) | public boolean isSuppressErrorUi() {
    method getExecutionScope (line 49) | public Object getExecutionScope() {
    method setExecutionScope (line 53) | public void setExecutionScope(Object executionContext) {

FILE: EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java
  class EventBusAnnotationProcessor (line 58) | @SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
    method getSupportedSourceVersion (line 73) | @Override
    method process (line 78) | @Override
    method collectSubscribers (line 129) | private void collectSubscribers(Set<? extends TypeElement> annotations...
    method checkHasNoErrors (line 146) | private boolean checkHasNoErrors(ExecutableElement element, Messager m...
    method checkForSubscribersToSkip (line 168) | private void checkForSubscribersToSkip(Messager messager, String myPac...
    method getParamTypeMirror (line 220) | private TypeMirror getParamTypeMirror(VariableElement param, Messager ...
    method getSuperclass (line 236) | private TypeElement getSuperclass(TypeElement type) {
    method getClassString (line 251) | private String getClassString(TypeElement typeElement, String myPackag...
    method cutPackage (line 265) | private String cutPackage(String paket, String className) {
    method getPackageElement (line 275) | private PackageElement getPackageElement(TypeElement subscriberClass) {
    method writeCreateSubscriberMethods (line 283) | private void writeCreateSubscriberMethods(BufferedWriter writer, List<...
    method createInfoIndexFile (line 320) | private void createInfoIndexFile(String index) {
    method writeIndexLines (line 371) | private void writeIndexLines(BufferedWriter writer, String myPackage) ...
    method isVisible (line 391) | private boolean isVisible(String myPackage, TypeElement typeElement) {
    method writeLine (line 409) | private void writeLine(BufferedWriter writer, int indentLevel, String....
    method writeLine (line 413) | private void writeLine(BufferedWriter writer, int indentLevel, int ind...
    method writeIndent (line 437) | private void writeIndent(BufferedWriter writer, int indentLevel) throw...

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/Test.java
  class Test (line 23) | public abstract class Test {
    method Test (line 33) | public Test(Context context, TestParams params) {
    method cancel (line 38) | public void cancel() {
    method prepareTest (line 43) | public abstract void prepareTest();
    method runTest (line 45) | public abstract void runTest();
    method getDisplayName (line 48) | public abstract String getDisplayName();
    method waitForReceivedEventCount (line 50) | protected void waitForReceivedEventCount(int expectedEventCount) {
    method getPrimaryResultMicros (line 60) | public long getPrimaryResultMicros() {
    method getPrimaryResultRate (line 64) | public double getPrimaryResultRate() {
    method getOtherTestResults (line 68) | public String getOtherTestResults() {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestEvent.java
  class TestEvent (line 20) | public class TestEvent {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestFinishedEvent.java
  class TestFinishedEvent (line 19) | public class TestFinishedEvent {
    method TestFinishedEvent (line 24) | public TestFinishedEvent(Test test, boolean isLastEvent) {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestParams.java
  class TestParams (line 24) | public class TestParams implements Serializable {
    method getEventCount (line 36) | public int getEventCount() {
    method setEventCount (line 40) | public void setEventCount(int iterations) {
    method getSubscriberCount (line 44) | public int getSubscriberCount() {
    method setSubscriberCount (line 48) | public void setSubscriberCount(int subscriberCount) {
    method getPublisherCount (line 52) | public int getPublisherCount() {
    method setPublisherCount (line 56) | public void setPublisherCount(int publisherCount) {
    method getThreadMode (line 60) | public ThreadMode getThreadMode() {
    method setThreadMode (line 64) | public void setThreadMode(ThreadMode threadMode) {
    method isEventInheritance (line 68) | public boolean isEventInheritance() {
    method setEventInheritance (line 72) | public void setEventInheritance(boolean eventInheritance) {
    method isIgnoreGeneratedIndex (line 76) | public boolean isIgnoreGeneratedIndex() {
    method setIgnoreGeneratedIndex (line 80) | public void setIgnoreGeneratedIndex(boolean ignoreGeneratedIndex) {
    method getTestClasses (line 84) | public ArrayList<Class<? extends Test>> getTestClasses() {
    method setTestClasses (line 88) | public void setTestClasses(ArrayList<Class<? extends Test>> testClasse...
    method getTestNumber (line 92) | public int getTestNumber() {
    method setTestNumber (line 96) | public void setTestNumber(int testNumber) {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunner.java
  class TestRunner (line 30) | public class TestRunner extends Thread {
    method TestRunner (line 35) | public TestRunner(Context context, TestParams testParams, EventBus con...
    method run (line 50) | public void run() {
    method getTests (line 76) | public List<Test> getTests() {
    method cancel (line 80) | public void cancel() {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java
  class TestRunnerActivity (line 35) | public class TestRunnerActivity extends Activity {
    method onCreate (line 41) | @Override
    method onResume (line 50) | @Override
    method onEventMainThread (line 65) | @Subscribe(threadMode = ThreadMode.MAIN)
    method onClickCancel (line 83) | public void onClickCancel(View view) {
    method onClickKillProcess (line 92) | public void onClickKillProcess(View view) {
    method onDestroy (line 96) | public void onDestroy() {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java
  class TestSetupActivity (line 35) | public class TestSetupActivity extends Activity {
    method onCreate (line 48) | @Override
    method checkEventBus (line 67) | public void checkEventBus(View v) {
    method startClick (line 74) | public void startClick(View v) {
    method initTestClasses (line 102) | @SuppressWarnings("unchecked")

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java
  class PerfTestEventBus (line 34) | public abstract class PerfTestEventBus extends Test {
    method PerfTestEventBus (line 42) | public PerfTestEventBus(Context context, TestParams params) {
    method prepareTest (line 52) | @Override
    method getSubscriberClassForThreadMode (line 65) | private Class<?> getSubscriberClassForThreadMode() {
    method getDisplayModifier (line 82) | private static String getDisplayModifier(TestParams params) {
    class Post (line 89) | public static class Post extends PerfTestEventBus {
      method Post (line 90) | public Post(Context context, TestParams params) {
      method prepareTest (line 94) | @Override
      method runTest (line 100) | public void runTest() {
      method getDisplayName (line 121) | @Override
    class RegisterAll (line 128) | public static class RegisterAll extends PerfTestEventBus {
      method RegisterAll (line 129) | public RegisterAll(Context context, TestParams params) {
      method runTest (line 133) | public void runTest() {
      method getDisplayName (line 140) | @Override
    class RegisterOneByOne (line 146) | public static class RegisterOneByOne extends PerfTestEventBus {
      method RegisterOneByOne (line 149) | public RegisterOneByOne(Context context, TestParams params) {
      method runTest (line 153) | public void runTest() {
      method getDisplayName (line 184) | @Override
    class RegisterFirstTime (line 190) | public static class RegisterFirstTime extends RegisterOneByOne {
      method RegisterFirstTime (line 192) | public RegisterFirstTime(Context context, TestParams params) {
      method getDisplayName (line 203) | @Override
    class SubscribeClassEventBusMain (line 210) | public class SubscribeClassEventBusMain {
      method onEventMainThread (line 211) | @Subscribe(threadMode = ThreadMode.MAIN)
      method dummy (line 216) | public void dummy() {
      method dummy2 (line 219) | public void dummy2() {
      method dummy3 (line 222) | public void dummy3() {
      method dummy4 (line 225) | public void dummy4() {
      method dummy5 (line 228) | public void dummy5() {
    class SubscribeClassEventBusMainOrdered (line 232) | public class SubscribeClassEventBusMainOrdered {
      method onEvent (line 233) | @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
      method dummy (line 238) | public void dummy() {
      method dummy2 (line 241) | public void dummy2() {
      method dummy3 (line 244) | public void dummy3() {
      method dummy4 (line 247) | public void dummy4() {
      method dummy5 (line 250) | public void dummy5() {
    class SubscribeClassEventBusBackground (line 254) | public class SubscribeClassEventBusBackground {
      method onEventBackgroundThread (line 255) | @Subscribe(threadMode = ThreadMode.BACKGROUND)
      method dummy (line 260) | public void dummy() {
      method dummy2 (line 263) | public void dummy2() {
      method dummy3 (line 266) | public void dummy3() {
      method dummy4 (line 269) | public void dummy4() {
      method dummy5 (line 272) | public void dummy5() {
    class SubscriberClassEventBusAsync (line 276) | public class SubscriberClassEventBusAsync {
      method onEventAsync (line 277) | @Subscribe(threadMode = ThreadMode.ASYNC)
      method dummy (line 282) | public void dummy() {
      method dummy2 (line 285) | public void dummy2() {
      method dummy3 (line 288) | public void dummy3() {
      method dummy4 (line 291) | public void dummy4() {
      method dummy5 (line 294) | public void dummy5() {
    method registerSubscribers (line 298) | private long registerSubscribers() {
    method registerUnregisterOneSubscribers (line 312) | private void registerUnregisterOneSubscribers() {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestOtto.java
  class PerfTestOtto (line 36) | public abstract class PerfTestOtto extends Test {
    method PerfTestOtto (line 44) | public PerfTestOtto(Context context, TestParams params) {
    method prepareTest (line 53) | @Override
    class Post (line 68) | public static class Post extends PerfTestOtto {
      method Post (line 69) | public Post(Context context, TestParams params) {
      method prepareTest (line 73) | @Override
      method runTest (line 79) | public void runTest() {
      method getDisplayName (line 95) | @Override
    class RegisterAll (line 101) | public static class RegisterAll extends PerfTestOtto {
      method RegisterAll (line 102) | public RegisterAll(Context context, TestParams params) {
      method runTest (line 106) | public void runTest() {
      method getDisplayName (line 113) | @Override
    class RegisterOneByOne (line 119) | public static class RegisterOneByOne extends PerfTestOtto {
      method RegisterOneByOne (line 122) | public RegisterOneByOne(Context context, TestParams params) {
      method runTest (line 126) | @SuppressWarnings("rawtypes")
      method getDisplayName (line 159) | @Override
    class RegisterFirstTime (line 165) | public static class RegisterFirstTime extends RegisterOneByOne {
      method RegisterFirstTime (line 167) | public RegisterFirstTime(Context context, TestParams params) {
      method getDisplayName (line 178) | @Override
    class Subscriber (line 185) | public class Subscriber extends Activity {
      method Subscriber (line 186) | public Subscriber() {
      method onEvent (line 189) | @Subscribe
      method dummy (line 194) | public void dummy() {
      method dummy2 (line 197) | public void dummy2() {
      method dummy3 (line 200) | public void dummy3() {
      method dummy4 (line 203) | public void dummy4() {
      method dummy5 (line 206) | public void dummy5() {
    method registerSubscribers (line 211) | private long registerSubscribers() {
    method registerUnregisterOneSubscribers (line 225) | private void registerUnregisterOneSubscribers() {

FILE: EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/SubscribeClassEventBusDefault.java
  class SubscribeClassEventBusDefault (line 23) | public class SubscribeClassEventBusDefault {
    method SubscribeClassEventBusDefault (line 26) | public SubscribeClassEventBusDefault(PerfTestEventBus perfTestEventBus) {
    method onEvent (line 30) | @Subscribe
    method dummy (line 35) | public void dummy() {
    method dummy2 (line 38) | public void dummy2() {
    method dummy3 (line 41) | public void dummy3() {
    method dummy4 (line 44) | public void dummy4() {
    method dummy5 (line 47) | public void dummy5() {

FILE: EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java
  class AbstractAndroidEventBusTest (line 33) | @RunWith(AndroidJUnit4.class)
    method AbstractAndroidEventBusTest (line 37) | public AbstractAndroidEventBusTest() {
    method AbstractAndroidEventBusTest (line 41) | public AbstractAndroidEventBusTest(boolean collectEventsReceived) {
    method setUpAndroid (line 45) | @Before
    method postInMainThread (line 51) | protected void postInMainThread(Object event) {
    class EventPostHandler (line 55) | @SuppressLint("HandlerLeak")
      method EventPostHandler (line 57) | public EventPostHandler(Looper looper) {
      method handleMessage (line 61) | @Override
      method post (line 66) | void post(Object event) {

FILE: EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java
  class AndroidComponentsAvailabilityTest (line 9) | public class AndroidComponentsAvailabilityTest {
    method shouldBeAvailable (line 11) | @Test

FILE: EventBusTest/src/org/greenrobot/eventbus/ClassMapPerfTest.java
  class ClassMapPerfTest (line 26) | public class ClassMapPerfTest /* extends TestCase */ {
    method testHashMapClassObject (line 31) | public void testHashMapClassObject() {
    method testIdentityHashMapClassObject (line 39) | public void testIdentityHashMapClassObject() {
    method testHashMapClassName (line 47) | public void testHashMapClassName() {

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java
  class EventBusAndroidActivityTest (line 33) | public class EventBusAndroidActivityTest extends AbstractEventBusTest {
    class WithIndex (line 35) | public static class WithIndex extends EventBusBasicTest {
      method dummy (line 36) | @Test
    method testRegisterAndPost (line 45) | @Test
    class TestActivity (line 62) | public static class TestActivity extends Activity {
      method onEvent (line 65) | @Subscribe

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java
  class EventBusAndroidCancelEventDeliveryTest (line 27) | @RunWith(AndroidJUnit4.class)
    method testCancelInMainThread (line 30) | @UiThreadTest

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java
  class EventBusAndroidMultithreadedTest (line 30) | @RunWith(AndroidJUnit4.class)
    method testSubscribeUnSubscribeAndPostMixedEventType (line 33) | @Test
    class SubscribeUnsubscribeThread (line 54) | public class SubscribeUnsubscribeThread extends Thread {
      method shutdown (line 57) | public void shutdown() {
      method run (line 61) | @Override
      method onEventMainThread (line 79) | @Subscribe(threadMode = ThreadMode.MAIN)
      method onEventBackgroundThread (line 84) | @Subscribe(threadMode = ThreadMode.BACKGROUND)
      method onEvent (line 89) | @Subscribe
      method onEventAsync (line 94) | @Subscribe(threadMode = ThreadMode.ASYNC)

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java
  class EventBusAndroidOrderTest (line 13) | public class EventBusAndroidOrderTest extends AbstractAndroidEventBusTest {
    method setUp (line 18) | @Before
    method tearDown (line 25) | @After
    method backgroundAndMainUnordered (line 31) | @Test
    method backgroundAndMainOrdered (line 52) | @Test
    method onEvent (line 73) | @Subscribe(threadMode = ThreadMode.MAIN)
    method onEvent (line 78) | @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    class OrderedEvent (line 83) | static class OrderedEvent {
      method OrderedEvent (line 86) | OrderedEvent(String thread) {

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java
  class EventBusBackgroundThreadTest (line 28) | public class EventBusBackgroundThreadTest extends AbstractAndroidEventBu...
    method testPostInCurrentThread (line 30) | @Test
    method testPostFromMain (line 40) | @Test
    method onEventBackgroundThread (line 50) | @Subscribe(threadMode = ThreadMode.BACKGROUND)

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java
  class EventBusMainThreadRacingTest (line 29) | public class EventBusMainThreadRacingTest extends AbstractAndroidEventBu...
    method testRacingThreads (line 37) | @Test
    method waitForHandler (line 78) | protected void waitForHandler(Handler handler) {
    method onEventMainThread (line 90) | @Subscribe(threadMode = ThreadMode.MAIN)
    class BackgroundPoster (line 99) | class BackgroundPoster extends Thread {
      method BackgroundPoster (line 102) | public BackgroundPoster() {
      method run (line 106) | @Override

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java
  class EventBusMainThreadTest (line 28) | public class EventBusMainThreadTest extends AbstractAndroidEventBusTest {
    method testPost (line 30) | @Test
    method testPostInBackgroundThread (line 40) | @Test
    method onEventMainThread (line 55) | @Subscribe(threadMode = ThreadMode.MAIN)

FILE: EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java
  class EventBusMethodModifiersTest (line 28) | public class EventBusMethodModifiersTest extends AbstractAndroidEventBus...
    method testRegisterForEventTypeAndPost (line 30) | @Test
    method onEvent (line 38) | @Subscribe
    method onEventMainThread (line 44) | @Subscribe(threadMode = ThreadMode.MAIN)
    method onEventBackgroundThread (line 50) | @Subscribe(threadMode = ThreadMode.BACKGROUND)
    method onEventAsync (line 56) | @Subscribe(threadMode = ThreadMode.ASYNC)

FILE: EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java
  class TestBackgroundPoster (line 6) | public class TestBackgroundPoster extends Thread {
    method TestBackgroundPoster (line 12) | TestBackgroundPoster(EventBus eventBus) {
    method run (line 17) | @Override
    method pollEvent (line 31) | private synchronized Object pollEvent() {
    method shutdown (line 47) | void shutdown() {
    method post (line 54) | void post(Object event) {

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java
  class EventBusAndroidOrderTestWithIndex (line 5) | public class EventBusAndroidOrderTestWithIndex extends EventBusAndroidOr...
    method setUp (line 7) | @Override

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java
  class EventBusBackgroundThreadTestWithIndex (line 25) | public class EventBusBackgroundThreadTestWithIndex extends EventBusBackg...
    method overwriteEventBus (line 26) | @Before
    method testIndex (line 31) | @Test

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java
  class EventBusBasicTestWithIndex (line 25) | public class EventBusBasicTestWithIndex extends EventBusBasicTest {
    method overwriteEventBus (line 26) | @Before
    method testIndex (line 31) | @Test

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusCancelEventDeliveryTestWithIndex.java
  class EventBusCancelEventDeliveryTestWithIndex (line 22) | public class EventBusCancelEventDeliveryTestWithIndex extends EventBusCa...
    method overwriteEventBus (line 23) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusFallbackToReflectionTestWithIndex.java
  class EventBusFallbackToReflectionTestWithIndex (line 23) | public class EventBusFallbackToReflectionTestWithIndex extends EventBusF...
    method overwriteEventBus (line 24) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusGenericsTestWithIndex.java
  class EventBusGenericsTestWithIndex (line 23) | public class EventBusGenericsTestWithIndex extends EventBusGenericsTest {
    method overwriteEventBus (line 24) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceDisabledTestWithIndex.java
  class EventBusInheritanceDisabledTestWithIndex (line 25) | public class EventBusInheritanceDisabledTestWithIndex extends EventBusIn...
    method setUp (line 26) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceTestWithIndex.java
  class EventBusInheritanceTestWithIndex (line 22) | public class EventBusInheritanceTestWithIndex extends EventBusInheritanc...
    method overwriteEventBus (line 23) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadRacingTestWithIndex.java
  class EventBusMainThreadRacingTestWithIndex (line 23) | public class EventBusMainThreadRacingTestWithIndex extends EventBusMainT...
    method overwriteEventBus (line 24) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadTestWithIndex.java
  class EventBusMainThreadTestWithIndex (line 23) | public class EventBusMainThreadTestWithIndex extends EventBusMainThreadT...
    method overwriteEventBus (line 24) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMethodModifiersTestWithIndex.java
  class EventBusMethodModifiersTestWithIndex (line 22) | public class EventBusMethodModifiersTestWithIndex extends EventBusMethod...
    method overwriteEventBus (line 23) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMultithreadedTestWithIndex.java
  class EventBusMultithreadedTestWithIndex (line 22) | public class EventBusMultithreadedTestWithIndex extends EventBusMultithr...
    method overwriteEventBus (line 23) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusNoSubscriberEventTestWithIndex.java
  class EventBusNoSubscriberEventTestWithIndex (line 22) | public class EventBusNoSubscriberEventTestWithIndex extends EventBusNoSu...
    method overwriteEventBus (line 23) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusOrderedSubscriptionsTestWithIndex.java
  class EventBusOrderedSubscriptionsTestWithIndex (line 22) | public class EventBusOrderedSubscriptionsTestWithIndex extends EventBusO...
    method overwriteEventBus (line 23) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusRegistrationRacingTestWithIndex.java
  class EventBusRegistrationRacingTestWithIndex (line 23) | public class EventBusRegistrationRacingTestWithIndex extends EventBusReg...
    method overwriteEventBus (line 24) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusStickyEventTestWithIndex.java
  class EventBusStickyEventTestWithIndex (line 22) | public class EventBusStickyEventTestWithIndex extends EventBusStickyEven...
    method overwriteEventBus (line 23) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberExceptionTestWithIndex.java
  class EventBusSubscriberExceptionTestWithIndex (line 23) | public class EventBusSubscriberExceptionTestWithIndex extends EventBusSu...
    method overwriteEventBus (line 24) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberInJarTestWithIndex.java
  class EventBusSubscriberInJarTestWithIndex (line 24) | public class EventBusSubscriberInJarTestWithIndex extends EventBusSubscr...
    method overwriteEventBus (line 25) | @Before

FILE: EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java
  class Indexed (line 23) | public class Indexed {
    method build (line 24) | static EventBus build() {

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java
  class AbstractEventBusTest (line 35) | public abstract class AbstractEventBusTest {
    method AbstractEventBusTest (line 47) | public AbstractEventBusTest() {
    method AbstractEventBusTest (line 51) | public AbstractEventBusTest(boolean collectEventsReceived) {
    method setUpBase (line 59) | @Before
    method waitForEventCount (line 65) | protected void waitForEventCount(int expectedCount, int maxMillis) {
    method trackEvent (line 84) | protected void trackEvent(Object event) {
    method assertEventCount (line 94) | protected void assertEventCount(int expectedEventCount) {
    method countDownAndAwaitLatch (line 98) | protected void countDownAndAwaitLatch(CountDownLatch latch, long secon...
    method awaitLatch (line 103) | protected void awaitLatch(CountDownLatch latch, long seconds) {
    method log (line 111) | protected void log(String msg) {
    method log (line 115) | protected void log(String msg, Throwable e) {

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBasicTest.java
  class EventBusBasicTest (line 30) | @SuppressWarnings({"WeakerAccess", "UnusedParameters", "unused"})
    class WithIndex (line 33) | public static class WithIndex extends EventBusBasicTest {
      method dummy (line 34) | @Test
    method testRegisterAndPost (line 48) | @Test
    method testPostWithoutSubscriber (line 64) | @Test
    method testUnregisterWithoutRegister (line 69) | @Test
    method testUnregisterNotLeaking (line 76) | @Test
    method testRegisterTwice (line 90) | @Test
    method testIsRegistered (line 101) | @Test
    method testPostWithTwoSubscriber (line 110) | @Test
    method testPostMultipleTimes (line 121) | @Test
    method testMultipleSubscribeMethodsForEvent (line 137) | @Test
    method testPostAfterUnregister (line 146) | @Test
    method testRegisterAndPostTwoTypes (line 154) | @Test
    method testRegisterUnregisterAndPostTwoTypes (line 165) | @Test
    method testPostOnDifferentEventBus (line 176) | @Test
    method testPostInEventHandler (line 183) | @Test
    method testHasSubscriberForEvent (line 195) | @Test
    method testHasSubscriberForEventSuperclass (line 206) | @Test
    method testHasSubscriberForEventImplementedInterface (line 218) | @Test
    method onEvent (line 232) | @Subscribe
    method onEvent (line 238) | @Subscribe
    method onEvent (line 244) | @Subscribe
    method onEvent2 (line 249) | @Subscribe
    method onEvent (line 254) | @Subscribe
    class StringEventSubscriber (line 259) | public static class StringEventSubscriber {
      method onEvent (line 262) | @Subscribe
    class CharSequenceSubscriber (line 268) | public static class CharSequenceSubscriber {
      method onEvent (line 269) | @Subscribe
    class ObjectSubscriber (line 274) | public static class ObjectSubscriber {
      method onEvent (line 275) | @Subscribe
    class MyEvent (line 280) | public class MyEvent {
    class MyEventExtended (line 283) | public class MyEventExtended extends MyEvent {
    class RepostInteger (line 286) | public class RepostInteger {
      method onEvent (line 290) | @Subscribe

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java
  class EventBusBuilderTest (line 26) | public class EventBusBuilderTest extends AbstractEventBusTest {
    method testThrowSubscriberException (line 28) | @Test
    method testDoNotSendSubscriberExceptionEvent (line 41) | @Test
    method testDoNotSendNoSubscriberEvent (line 50) | @Test
    method testInstallDefaultEventBus (line 58) | @Test
    method testEventInheritance (line 74) | @Test
    class SubscriberExceptionEventTracker (line 81) | public class SubscriberExceptionEventTracker {
      method onEvent (line 82) | @Subscribe
    class NoSubscriberEventTracker (line 88) | public class NoSubscriberEventTracker {
      method onEvent (line 89) | @Subscribe
    class ThrowingSubscriber (line 95) | public class ThrowingSubscriber {
      method onEvent (line 96) | @Subscribe

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java
  class EventBusCancelEventDeliveryTest (line 26) | public class EventBusCancelEventDeliveryTest extends AbstractEventBusTest {
    method testCancel (line 30) | @Test
    method testCancelInBetween (line 44) | @Test
    method testCancelOutsideEventHandler (line 53) | @Test
    method testCancelWrongEvent (line 63) | @Test
    class Subscriber (line 71) | public class Subscriber {
      method Subscriber (line 75) | public Subscriber(int prio, boolean cancel) {
      method onEvent (line 80) | @Subscribe
      method onEvent1 (line 85) | @Subscribe(priority = 1)
      method onEvent2 (line 90) | @Subscribe(priority = 2)
      method onEvent3 (line 95) | @Subscribe(priority = 3)
      method handleEvent (line 100) | private void handleEvent(String event, int prio) {
    class SubscriberCancelOtherEvent (line 110) | public class SubscriberCancelOtherEvent {
      method onEvent (line 111) | @Subscribe
    class SubscriberMainThread (line 121) | public class SubscriberMainThread {
      method onEventMainThread (line 124) | @Subscribe(threadMode = ThreadMode.MAIN)

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java
  class EventBusFallbackToReflectionTest (line 23) | public class EventBusFallbackToReflectionTest extends AbstractEventBusTe...
    class PrivateEvent (line 24) | private class PrivateEvent {
    class PublicClass (line 27) | public class PublicClass {
      method onEvent (line 28) | @Subscribe
    class PrivateClass (line 34) | private class PrivateClass {
      method onEvent (line 35) | @Subscribe
    class PublicWithPrivateSuperClass (line 41) | public class PublicWithPrivateSuperClass extends PrivateClass {
      method onEvent (line 42) | @Subscribe
    class PublicClassWithPrivateEvent (line 48) | public class PublicClassWithPrivateEvent {
      method onEvent (line 49) | @Subscribe
    class PublicClassWithPublicAndPrivateEvent (line 55) | public class PublicClassWithPublicAndPrivateEvent {
      method onEvent (line 56) | @Subscribe
      method onEvent (line 61) | @Subscribe
    class PublicWithPrivateEventInSuperclass (line 67) | public class PublicWithPrivateEventInSuperclass extends PublicClassWit...
      method onEvent (line 68) | @Subscribe
    method EventBusFallbackToReflectionTest (line 74) | public EventBusFallbackToReflectionTest() {
    method testAnonymousSubscriberClass (line 78) | @Test
    method testAnonymousSubscriberClassWithPublicSuperclass (line 93) | @Test
    method testAnonymousSubscriberClassWithPrivateSuperclass (line 108) | @Test
    method testSubscriberClassWithPrivateEvent (line 116) | @Test
    method testSubscriberClassWithPublicAndPrivateEvent (line 125) | @Test
    method testSubscriberExtendingClassWithPrivateEvent (line 139) | @Test

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusGenericsTest.java
  class EventBusGenericsTest (line 21) | public class EventBusGenericsTest extends AbstractEventBusTest {
    class GenericEvent (line 22) | public static class GenericEvent<T> {
    class GenericEventSubscriber (line 26) | public class GenericEventSubscriber<T> {
      method onGenericEvent (line 27) | @Subscribe
    class FullGenericEventSubscriber (line 33) | public class FullGenericEventSubscriber<T> {
      method onGenericEvent (line 34) | @Subscribe
    class GenericNumberEventSubscriber (line 40) | public class GenericNumberEventSubscriber<T extends Number> {
      method onGenericEvent (line 41) | @Subscribe
    class GenericFloatEventSubscriber (line 47) | public class GenericFloatEventSubscriber extends GenericNumberEventSub...
    method testGenericEventAndSubscriber (line 50) | @Test
    method testGenericEventAndSubscriber_TypeErasure (line 58) | @Test
    method testGenericEventAndSubscriber_BaseType (line 67) | @Test
    method testGenericEventAndSubscriber_Subclass (line 78) | @Test

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusIndexTest.java
  class EventBusIndexTest (line 26) | public class EventBusIndexTest {
    method testManualIndexWithoutAnnotation (line 30) | @Test
    method someMethodWithoutAnnotation (line 51) | public void someMethodWithoutAnnotation(String value) {

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java
  class EventBusInheritanceDisabledSubclassNoMethod (line 4) | public class EventBusInheritanceDisabledSubclassNoMethod extends EventBu...

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java
  class EventBusInheritanceDisabledSubclassTest (line 6) | public class EventBusInheritanceDisabledSubclassTest extends EventBusInh...
    method onEvent (line 10) | @Subscribe
    method testEventClassHierarchy (line 15) | @Override

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java
  class EventBusInheritanceDisabledTest (line 26) | public class EventBusInheritanceDisabledTest {
    method setUp (line 36) | @Before
    method testEventClassHierarchy (line 41) | @Test
    method testEventClassHierarchySticky (line 58) | @Test
    method testEventInterfaceHierarchy (line 69) | @Test
    method testEventSuperInterfaceHierarchy (line 81) | @Test
    method testSubscriberClassHierarchy (line 91) | @Test
    method testSubscriberClassHierarchyWithoutNewSubscriberMethod (line 112) | @Test
    method onEvent (line 131) | @Subscribe
    method onEvent (line 136) | @Subscribe
    method onEvent (line 141) | @Subscribe
    method onEvent (line 146) | @Subscribe
    method onEvent (line 151) | @Subscribe
    type MyEventInterface (line 156) | public static interface MyEventInterface {
    class MyEvent (line 159) | public static class MyEvent implements MyEventInterface {
    type MyEventInterfaceExtended (line 162) | public static interface MyEventInterfaceExtended extends MyEventInterf...
    class MyEventExtended (line 165) | public static class MyEventExtended extends MyEvent implements MyEvent...
    class StickySubscriber (line 168) | public class StickySubscriber {
      method onEvent (line 169) | @Subscribe(sticky = true)
      method onEvent (line 174) | @Subscribe(sticky = true)
      method onEvent (line 179) | @Subscribe(sticky = true)
      method onEvent (line 184) | @Subscribe(sticky = true)
      method onEvent (line 189) | @Subscribe(sticky = true)

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java
  class EventBusInheritanceSubclassNoMethodTest (line 4) | public class EventBusInheritanceSubclassNoMethodTest extends EventBusInh...

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java
  class EventBusInheritanceSubclassTest (line 6) | public class EventBusInheritanceSubclassTest extends EventBusInheritance...
    method onEvent (line 9) | @Subscribe
    method testEventClassHierarchy (line 14) | @Override

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java
  class EventBusInheritanceTest (line 26) | public class EventBusInheritanceTest {
    method setUp (line 36) | @Before
    method testEventClassHierarchy (line 41) | @Test
    method testEventClassHierarchySticky (line 58) | @Test
    method testEventInterfaceHierarchy (line 69) | @Test
    method testEventSuperInterfaceHierarchy (line 81) | @Test
    method testSubscriberClassHierarchy (line 91) | @Test
    method testSubscriberClassHierarchyWithoutNewSubscriberMethod (line 111) | @Test
    method onEvent (line 130) | @Subscribe
    method onEvent (line 135) | @Subscribe
    method onEvent (line 140) | @Subscribe
    method onEvent (line 145) | @Subscribe
    method onEvent (line 150) | @Subscribe
    type MyEventInterface (line 155) | public static interface MyEventInterface {
    class MyEvent (line 158) | public static class MyEvent implements MyEventInterface {
    type MyEventInterfaceExtended (line 161) | public static interface MyEventInterfaceExtended extends MyEventInterf...
    class MyEventExtended (line 164) | public static class MyEventExtended extends MyEvent implements MyEvent...
    class StickySubscriber (line 167) | public class StickySubscriber {
      method onEvent (line 168) | @Subscribe(sticky = true)
      method onEvent (line 173) | @Subscribe(sticky = true)
      method onEvent (line 178) | @Subscribe(sticky = true)
      method onEvent (line 183) | @Subscribe(sticky = true)
      method onEvent (line 188) | @Subscribe(sticky = true)

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusMultithreadedTest.java
  class EventBusMultithreadedTest (line 27) | public class EventBusMultithreadedTest extends AbstractEventBusTest {
    method testPost01Thread (line 41) | @Test
    method testPost04Threads (line 46) | @Test
    method testPost40Threads (line 51) | @Test
    method testPostMixedEventType01Thread (line 56) | @Test
    method testPostMixedEventType04Threads (line 61) | @Test
    method testPostMixedEventType40Threads (line 66) | @Test
    method runThreadsSingleEventType (line 71) | private void runThreadsSingleEventType(int threadCount) throws Interru...
    method runThreadsMixedEventType (line 89) | private void runThreadsMixedEventType(int threadCount) throws Interrup...
    method runThreadsMixedEventType (line 93) | void runThreadsMixedEventType(int count, int threadCount) throws Inter...
    method triggerAndWaitForThreads (line 127) | private long triggerAndWaitForThreads(List<PosterThread> threads, Coun...
    method startThreads (line 140) | private List<PosterThread> startThreads(CountDownLatch latch, int thre...
    method onEventBackgroundThread (line 150) | @Subscribe(threadMode = ThreadMode.BACKGROUND)
    method onEventMainThread (line 157) | @Subscribe(threadMode = ThreadMode.MAIN)
    method onEventAsync (line 164) | @Subscribe(threadMode = ThreadMode.ASYNC)
    method onEvent (line 171) | @Subscribe
    class PosterThread (line 177) | class PosterThread extends Thread {
      method PosterThread (line 183) | public PosterThread(CountDownLatch latch, int iterations, Object eve...
      method run (line 189) | @Override

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java
  class EventBusNoSubscriberEventTest (line 26) | public class EventBusNoSubscriberEventTest extends AbstractEventBusTest {
    method testNoSubscriberEvent (line 28) | @Test
    method testNoSubscriberEventAfterUnregister (line 39) | @Test
    method testBadNoSubscriberSubscriber (line 47) | @Test
    method onEvent (line 60) | @Subscribe
    method onEvent (line 65) | @Subscribe
    class DummySubscriber (line 70) | public static class DummySubscriber {
      method onEvent (line 71) | @SuppressWarnings("unused")
    class BadNoSubscriberSubscriber (line 77) | public class BadNoSubscriberSubscriber {
      method onEvent (line 78) | @Subscribe

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java
  class EventBusOrderedSubscriptionsTest (line 28) | public class EventBusOrderedSubscriptionsTest extends AbstractEventBusTe...
    method testOrdered (line 34) | @Test
    method testOrderedMainThread (line 39) | @Test
    method testOrderedBackgroundThread (line 44) | @Test
    method testOrderedSticky (line 49) | @Test
    method testOrderedMainThreadSticky (line 54) | @Test
    method testOrderedBackgroundThreadSticky (line 59) | @Test
    method runTestOrdered (line 64) | protected void runTestOrdered(Object event, boolean sticky, int expect...
    class PrioSubscriber (line 75) | public final class PrioSubscriber {
      method onEventP1 (line 76) | @Subscribe(priority = 1)
      method onEventM1 (line 81) | @Subscribe(priority = -1)
      method onEventP0 (line 86) | @Subscribe(priority = 0)
      method onEventP10 (line 91) | @Subscribe(priority = 10)
      method onEventM100 (line 96) | @Subscribe(priority = -100)
      method onEventMainThreadM1 (line 102) | @Subscribe(threadMode = ThreadMode.MAIN, priority = -1)
      method onEventMainThreadP0 (line 107) | @Subscribe(threadMode = ThreadMode.MAIN)
      method onEventMainThreadP1 (line 112) | @Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
      method onEventBackgroundThreadP1 (line 117) | @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 1)
      method onEventBackgroundThreadP0 (line 122) | @Subscribe(threadMode = ThreadMode.BACKGROUND)
      method onEventBackgroundThreadM1 (line 127) | @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = -1)
      method handleEvent (line 132) | protected void handleEvent(int prio, Object event) {
    class PrioSubscriberSticky (line 144) | public final class PrioSubscriberSticky {
      method onEventP1 (line 145) | @Subscribe(priority = 1, sticky = true)
      method onEventM1 (line 151) | @Subscribe(priority = -1, sticky = true)
      method onEventP0 (line 156) | @Subscribe(priority = 0, sticky = true)
      method onEventP10 (line 161) | @Subscribe(priority = 10, sticky = true)
      method onEventM100 (line 166) | @Subscribe(priority = -100, sticky = true)
      method onEventMainThreadM1 (line 171) | @Subscribe(threadMode = ThreadMode.MAIN, priority = -1, sticky = true)
      method onEventMainThreadP0 (line 176) | @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
      method onEventMainThreadP1 (line 181) | @Subscribe(threadMode = ThreadMode.MAIN, priority = 1, sticky = true)
      method onEventBackgroundThreadP1 (line 186) | @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 1, sticky ...
      method onEventBackgroundThreadP0 (line 191) | @Subscribe(threadMode = ThreadMode.BACKGROUND, sticky = true)
      method onEventBackgroundThreadM1 (line 196) | @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = -1, sticky...
      method handleEvent (line 201) | protected void handleEvent(int prio, Object event) {

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java
  class EventBusRegistrationRacingTest (line 31) | public class EventBusRegistrationRacingTest extends AbstractEventBusTest {
    method testRacingRegistrations (line 45) | @Test
    method startThreads (line 68) | private List<SubscriberThread> startThreads() {
    class SubscriberThread (line 78) | public class SubscriberThread implements Runnable {
      method run (line 81) | @Override
      method onEvent (line 95) | @Subscribe

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusStickyEventTest.java
  class EventBusStickyEventTest (line 25) | public class EventBusStickyEventTest extends AbstractEventBusTest {
    method testPostSticky (line 27) | @Test
    method testPostStickyTwoEvents (line 35) | @Test
    method testPostStickyTwoSubscribers (line 43) | @Test
    method testPostStickyRegisterNonSticky (line 59) | @Test
    method testPostNonStickyRegisterSticky (line 67) | @Test
    method testPostStickyTwice (line 75) | @Test
    method testPostStickyThenPostNormal (line 83) | @Test
    method testPostStickyWithRegisterAndUnregister (line 91) | @Test
    method testPostStickyAndGet (line 112) | @Test
    method testPostStickyRemoveClass (line 118) | @Test
    method testPostStickyRemoveEvent (line 128) | @Test
    method testPostStickyRemoveAll (line 138) | @Test
    method testRemoveStickyEventInSubscriber (line 150) | @Test
    method onEvent (line 160) | @Subscribe(sticky = true)
    method onEvent (line 165) | @Subscribe(sticky = true)
    class RemoveStickySubscriber (line 170) | public class RemoveStickySubscriber {
      method onEvent (line 171) | @SuppressWarnings("unused")
    class NonStickySubscriber (line 178) | public class NonStickySubscriber {
      method onEvent (line 179) | @Subscribe
      method onEvent (line 184) | @Subscribe
    class StickyIntTestSubscriber (line 190) | public class StickyIntTestSubscriber {
      method onEvent (line 191) | @Subscribe(sticky = true)

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java
  class EventBusSubscriberExceptionTest (line 26) | public class EventBusSubscriberExceptionTest extends AbstractEventBusTest {
    method testSubscriberExceptionEvent (line 28) | @Test
    method testBadExceptionSubscriber (line 41) | @Test
    method onEvent (line 50) | @Subscribe
    method onEvent (line 55) | @Subscribe
    class BadExceptionSubscriber (line 60) | public class BadExceptionSubscriber {
      method onEvent (line 61) | @Subscribe

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java
  class EventBusSubscriberInJarTest (line 22) | public class EventBusSubscriberInJarTest {
    method testSubscriberInJar (line 25) | @Test

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java
  class EventBusSubscriberLegalTest (line 25) | public class EventBusSubscriberLegalTest extends AbstractEventBusTest {
    method testSubscriberLegal (line 27) | @Test
    method testSubscriberLegalAbstract (line 54) | public void testSubscriberLegalAbstract() {
    method onEvent (line 61) | @Subscribe
    class Abstract (line 72) | public static abstract class Abstract {
      method onEvent (line 73) | @Subscribe
    class AbstractImpl (line 77) | public class AbstractImpl extends Abstract {
      method onEvent (line 79) | @Override

FILE: EventBusTestJava/src/main/java/org/greenrobot/eventbus/IntTestEvent.java
  class IntTestEvent (line 22) | public class IntTestEvent {
    method IntTestEvent (line 25) | public IntTestEvent(int value) {

FILE: EventBusTestSubscriberInJar/src/org/greenrobot/eventbus/SubscriberInJar.java
  class SubscriberInJar (line 7) | public class SubscriberInJar {
    method collectString (line 10) | @Subscribe
    method getCollectedStrings (line 15) | public List<String> getCollectedStrings() {

FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/HandlerPoster.java
  class HandlerPoster (line 23) | public class HandlerPoster extends Handler implements Poster {
    method HandlerPoster (line 30) | public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisIn...
    method enqueue (line 37) | public void enqueue(Subscription subscription, Object event) {
    method handleMessage (line 50) | @Override

FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java
  class AndroidComponentsImpl (line 6) | public class AndroidComponentsImpl extends AndroidComponents {
    method AndroidComponentsImpl (line 8) | public AndroidComponentsImpl() {

FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java
  class AndroidLogger (line 23) | public class AndroidLogger implements Logger {
    method AndroidLogger (line 27) | public AndroidLogger(String tag) {
    method log (line 31) | public void log(Level level, String msg) {
    method log (line 37) | public void log(Level level, String msg, Throwable th) {
    method mapLevel (line 44) | private int mapLevel(Level level) {

FILE: eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java
  class DefaultAndroidMainThreadSupport (line 9) | public class DefaultAndroidMainThreadSupport implements MainThreadSupport {
    method isMainThread (line 11) | @Override
    method createPoster (line 16) | @Override
Condensed preview — 134 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (365K chars).
[
  {
    "path": ".github/workflows/gradle.yml",
    "chars": 693,
    "preview": "# This workflow will build a Java project with Gradle\n# For more information see: https://help.github.com/actions/langua"
  },
  {
    "path": ".gitignore",
    "chars": 341,
    "preview": "# 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\nbi"
  },
  {
    "path": "COMPARISON.md",
    "chars": 2926,
    "preview": "EventBus Comparison\n===================\n\nComparison with Square's Otto\n-----------------------------\nOtto is another eve"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2173,
    "preview": "Before you create an Issue...\n=============================\n\nThere are better Places for Support\n-----------------------"
  },
  {
    "path": "EventBus/build.gradle",
    "chars": 1299,
    "preview": "apply plugin: 'java'\n\ngroup = rootProject.group\nversion = rootProject.version\n\njava.sourceCompatibility = JavaVersion.VE"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/AsyncPoster.java",
    "chars": 1499,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/BackgroundPoster.java",
    "chars": 2418,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/EventBus.java",
    "chars": 24331,
    "preview": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/EventBusBuilder.java",
    "chars": 7302,
    "preview": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/EventBusException.java",
    "chars": 1230,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Logger.java",
    "chars": 2111,
    "preview": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/MainThreadSupport.java",
    "chars": 921,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/NoSubscriberEvent.java",
    "chars": 1229,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/PendingPost.java",
    "chars": 1998,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/PendingPostQueue.java",
    "chars": 1692,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Poster.java",
    "chars": 1054,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Subscribe.java",
    "chars": 1660,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/SubscriberExceptionEvent.java",
    "chars": 1592,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/SubscriberMethod.java",
    "chars": 2457,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java",
    "chars": 12484,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/Subscription.java",
    "chars": 1725,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/ThreadMode.java",
    "chars": 3360,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/android/AndroidComponents.java",
    "chars": 884,
    "preview": "package org.greenrobot.eventbus.android;\n\nimport org.greenrobot.eventbus.Logger;\nimport org.greenrobot.eventbus.MainThre"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/android/AndroidDependenciesDetector.java",
    "chars": 1519,
    "preview": "package org.greenrobot.eventbus.android;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.M"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/AbstractSubscriberInfo.java",
    "chars": 3195,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SimpleSubscriberInfo.java",
    "chars": 1698,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfo.java",
    "chars": 1018,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SubscriberInfoIndex.java",
    "chars": 834,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/meta/SubscriberMethodInfo.java",
    "chars": 1559,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/AsyncExecutor.java",
    "chars": 4595,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/ExceptionToResourceMapping.java",
    "chars": 3237,
    "preview": "/*\n * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/HasExecutionScope.java",
    "chars": 810,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBus/src/org/greenrobot/eventbus/util/ThrowableFailureEvent.java",
    "chars": 1835,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusAnnotationProcessor/build.gradle",
    "chars": 1678,
    "preview": "apply plugin: 'java'\n\ngroup = rootProject.group\nversion = rootProject.version\n\njava.sourceCompatibility = JavaVersion.VE"
  },
  {
    "path": "EventBusAnnotationProcessor/res/META-INF/services/javax.annotation.processing.Processor",
    "chars": 72,
    "preview": "org.greenrobot.eventbus.annotationprocessor.EventBusAnnotationProcessor\n"
  },
  {
    "path": "EventBusAnnotationProcessor/src/org/greenrobot/eventbus/annotationprocessor/EventBusAnnotationProcessor.java",
    "chars": 20242,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/.gitignore",
    "chars": 10,
    "preview": "/bin\n/gen\n"
  },
  {
    "path": "EventBusPerformance/AndroidManifest.xml",
    "chars": 1005,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    packag"
  },
  {
    "path": "EventBusPerformance/build.gradle",
    "chars": 1121,
    "preview": "buildscript {\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        // Note: Inte"
  },
  {
    "path": "EventBusPerformance/proguard-project.txt",
    "chars": 781,
    "preview": "# To enable ProGuard in your project, edit project.properties\n# to define the proguard.config property as described in t"
  },
  {
    "path": "EventBusPerformance/project.properties",
    "chars": 563,
    "preview": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# T"
  },
  {
    "path": "EventBusPerformance/res/layout/activity_runtests.xml",
    "chars": 1881,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    an"
  },
  {
    "path": "EventBusPerformance/res/layout/activity_setuptests.xml",
    "chars": 5748,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    andr"
  },
  {
    "path": "EventBusPerformance/res/values/strings.xml",
    "chars": 1295,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"app_name\">EventBus Performance</string>\n    <strin"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/Test.java",
    "chars": 2142,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestEvent.java",
    "chars": 746,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestFinishedEvent.java",
    "chars": 923,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestParams.java",
    "chars": 2729,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunner.java",
    "chars": 2664,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestRunnerActivity.java",
    "chars": 3624,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/TestSetupActivity.java",
    "chars": 5145,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestEventBus.java",
    "chars": 10077,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/PerfTestOtto.java",
    "chars": 7161,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusPerformance/src/org/greenrobot/eventbusperf/testsubject/SubscribeClassEventBusDefault.java",
    "chars": 1314,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/AndroidManifest.xml",
    "chars": 487,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\r\n    xmlns:"
  },
  {
    "path": "EventBusTest/build.gradle",
    "chars": 1835,
    "preview": "buildscript {\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        // Note: Inte"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/AbstractAndroidEventBusTest.java",
    "chars": 2043,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/AndroidComponentsAvailabilityTest.java",
    "chars": 414,
    "preview": "package org.greenrobot.eventbus;\n\nimport org.greenrobot.eventbus.android.AndroidComponents;\nimport org.junit.Test;\n\nimpo"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/ClassMapPerfTest.java",
    "chars": 1803,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidActivityTest.java",
    "chars": 2101,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidCancelEventDeliveryTest.java",
    "chars": 1377,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidMultithreadedTest.java",
    "chars": 3398,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusAndroidOrderTest.java",
    "chars": 2306,
    "preview": "package org.greenrobot.eventbus;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport org.junit.After;\nimport o"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusBackgroundThreadTest.java",
    "chars": 1752,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadRacingTest.java",
    "chars": 3841,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusMainThreadTest.java",
    "chars": 1823,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/EventBusMethodModifiersTest.java",
    "chars": 1924,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/TestBackgroundPoster.java",
    "chars": 1796,
    "preview": "package org.greenrobot.eventbus;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class TestBackgroundPoster "
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusAndroidOrderTestWithIndex.java",
    "chars": 308,
    "preview": "package org.greenrobot.eventbus.indexed;\n\nimport org.greenrobot.eventbus.EventBusAndroidOrderTest;\n\npublic class EventBu"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBackgroundThreadTestWithIndex.java",
    "chars": 1157,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusBasicTestWithIndex.java",
    "chars": 1124,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusCancelEventDeliveryTestWithIndex.java",
    "chars": 986,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusFallbackToReflectionTestWithIndex.java",
    "chars": 991,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusGenericsTestWithIndex.java",
    "chars": 954,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceDisabledTestWithIndex.java",
    "chars": 1137,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusInheritanceTestWithIndex.java",
    "chars": 962,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadRacingTestWithIndex.java",
    "chars": 978,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMainThreadTestWithIndex.java",
    "chars": 960,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMethodModifiersTestWithIndex.java",
    "chars": 974,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusMultithreadedTestWithIndex.java",
    "chars": 968,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusNoSubscriberEventTestWithIndex.java",
    "chars": 980,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusOrderedSubscriptionsTestWithIndex.java",
    "chars": 989,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusRegistrationRacingTestWithIndex.java",
    "chars": 984,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusStickyEventTestWithIndex.java",
    "chars": 962,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberExceptionTestWithIndex.java",
    "chars": 987,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/EventBusSubscriberInJarTestWithIndex.java",
    "chars": 1096,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTest/src/org/greenrobot/eventbus/indexed/Indexed.java",
    "chars": 1066,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/build.gradle",
    "chars": 748,
    "preview": "apply plugin: \"java-library\"\n\njava.sourceCompatibility = JavaVersion.VERSION_1_8\njava.targetCompatibility = JavaVersion."
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/AbstractEventBusTest.java",
    "chars": 3762,
    "preview": "/*\n * Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBasicTest.java",
    "chars": 8920,
    "preview": "/*\n * Copyright (C) 2012-2017 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusBuilderTest.java",
    "chars": 3243,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusCancelEventDeliveryTest.java",
    "chars": 3852,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusFallbackToReflectionTest.java",
    "chars": 4253,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusGenericsTest.java",
    "chars": 2912,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusIndexTest.java",
    "chars": 2014,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassNoMethod.java",
    "chars": 205,
    "preview": "package org.greenrobot.eventbus;\n\n// Need to use upper class or Android test runner does not pick it up\npublic class Eve"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledSubclassTest.java",
    "chars": 487,
    "preview": "package org.greenrobot.eventbus;\n\nimport org.junit.Ignore;\n\n// Need to use upper class or Android test runner does not p"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceDisabledTest.java",
    "chars": 5712,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassNoMethodTest.java",
    "chars": 193,
    "preview": "package org.greenrobot.eventbus;\n\n// Need to use upper class or Android test runner does not pick it up\npublic class Eve"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceSubclassTest.java",
    "chars": 471,
    "preview": "package org.greenrobot.eventbus;\n\nimport org.junit.Ignore;\n\n// Need to use upper class or Android test runner does not p"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusInheritanceTest.java",
    "chars": 5622,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusMultithreadedTest.java",
    "chars": 7186,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusNoSubscriberEventTest.java",
    "chars": 2620,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusOrderedSubscriptionsTest.java",
    "chars": 6326,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusRegistrationRacingTest.java",
    "chars": 3560,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusStickyEventTest.java",
    "chars": 6220,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberExceptionTest.java",
    "chars": 2168,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberInJarTest.java",
    "chars": 1206,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/EventBusSubscriberLegalTest.java",
    "chars": 2531,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestJava/src/main/java/org/greenrobot/eventbus/IntTestEvent.java",
    "chars": 922,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "EventBusTestSubscriberInJar/build.gradle",
    "chars": 593,
    "preview": "apply plugin: \"java-library\"\n\ngroup = \"de.greenrobot\"\nversion = \"3.0.0\"\njava.sourceCompatibility = JavaVersion.VERSION_1"
  },
  {
    "path": "EventBusTestSubscriberInJar/src/org/greenrobot/eventbus/SubscriberInJar.java",
    "chars": 422,
    "preview": "package org.greenrobot.eventbus;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Helper class used by test insi"
  },
  {
    "path": "LICENSE",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "README.md",
    "chars": 4128,
    "preview": "EventBus\n========\n[EventBus](https://greenrobot.org/eventbus/) is a publish/subscribe event bus for Android and Java.<br"
  },
  {
    "path": "build.gradle",
    "chars": 1394,
    "preview": "buildscript {\n    ext {\n        _compileSdkVersion = 30 // Android 11 (R)\n    }\n    repositories {\n        mavenCentral("
  },
  {
    "path": "eventbus-android/.gitignore",
    "chars": 6,
    "preview": "/build"
  },
  {
    "path": "eventbus-android/README.md",
    "chars": 404,
    "preview": "# EventBus for Android\n\nDespite its name this module is actually published as `org.greenrobot:eventbus` as an Android li"
  },
  {
    "path": "eventbus-android/build.gradle",
    "chars": 1558,
    "preview": "buildscript {\n    repositories {\n        google()\n        mavenCentral()\n    }\n\n    dependencies {\n        // Note: Inte"
  },
  {
    "path": "eventbus-android/consumer-rules.pro",
    "chars": 535,
    "preview": "-keepattributes *Annotation*\n-keepclassmembers class * {\n    @org.greenrobot.eventbus.Subscribe <methods>;\n}\n-keep enum "
  },
  {
    "path": "eventbus-android/proguard-rules.pro",
    "chars": 750,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "eventbus-android/src/main/AndroidManifest.xml",
    "chars": 104,
    "preview": "<?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",
    "chars": 2973,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidComponentsImpl.java",
    "chars": 327,
    "preview": "package org.greenrobot.eventbus.android;\n\n/**\n * Used via reflection in the Java library by {@link AndroidDependenciesDe"
  },
  {
    "path": "eventbus-android/src/main/java/org/greenrobot/eventbus/android/AndroidLogger.java",
    "chars": 1828,
    "preview": "/*\n * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)\n *\n * Licensed under the Apache Licen"
  },
  {
    "path": "eventbus-android/src/main/java/org/greenrobot/eventbus/android/DefaultAndroidMainThreadSupport.java",
    "chars": 585,
    "preview": "package org.greenrobot.eventbus.android;\n\nimport android.os.Looper;\nimport org.greenrobot.eventbus.EventBus;\nimport org."
  },
  {
    "path": "gradle/publish.gradle",
    "chars": 2953,
    "preview": "// Configures common publishing settings.\n\napply plugin: \"maven-publish\"\napply plugin: \"signing\"\n\npublishing {\n    publi"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 202,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "gradlew",
    "chars": 5766,
    "preview": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0"
  },
  {
    "path": "gradlew.bat",
    "chars": 2763,
    "preview": "@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 (th"
  },
  {
    "path": "javadoc-style/stylesheet.css",
    "chars": 12808,
    "preview": "/* Javadoc style sheet */\n/*\nOverall document style\n*/\n\n@import url('resources/fonts/dejavu.css');\n\nbody {\n    backgroun"
  },
  {
    "path": "settings.gradle",
    "chars": 333,
    "preview": "include ':EventBus'\ninclude ':EventBusAnnotationProcessor'\ninclude ':EventBusTestJava'\ninclude ':EventBusTest'\ninclude '"
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the greenrobot/EventBus GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 134 files (333.0 KB), approximately 76.9k tokens, and a symbol index with 735 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!