This section is designed to give engineers a 5-minute overview of how
cross-profile calls work with the SDK and how they can be tested. Don't try to
build anything yet - this isn't designed to be used as a reference or a guide,
but just as an introduction.

## Custom profile-aware classes and methods

The connected apps SDK lets you to annotate your own classes and methods as
cross-profile. This generates classes and methods that allow you to execute the
annotated method on any profile.

For example, consider the following class, with SDK annotation added:

    public class CalendarDatabase {

      @CrossProfile // SDK annotation
      public void deleteEvent(Event event, Account account) {
        // complex logic with database calls
      }
    }

This generates a class prefixed with Profile, allowing you to call this API on
the profile of your choice. For example: `java
profileCalendarDatabase.work().deleteEvent(event, account);`

### More complex examples

More realistically, your classes and methods will be more complex. For example,
your existing API could use `ListenableFuture` return types and you might need
to combine results from both profiles. Consider this example:

    public class CalendarDatabase {

      @CrossProfile // SDK annotation
      public ListenableFuture<Collection<Event>> getEvents() {
        // complex logic with database calls
      }
    }

    // Merge results from both profiles into a set
    profileCalendarDatabase.both()
      .getEvents()
      .transform((Map<Profile, Collection<Event>> events) -> {
        return events.values()
            .stream()
            .flatMap(Collection::stream)
            .collect(Collectors.toSet());
      }, directExecutor());

These generated classes and methods work as expected with full type safety and
IDE code completion.

Each return and parameter type of your annotated APIs must be supported by the
SDK, but it fully supports nesting and generics of lists, sets, arrays,
primitives, any parcelable type, and any serializable type, in addition to
`ListenableFuture`, `Optional`, and protos. It's also possible for you to add
support for types not natively supported by the SDK. As an extreme example, it
would seamlessly support `ListenableFuture<List<Map<CustomProto,
CustomParcelableType[]>>>`.

### Testing

The SDK is designed to simplify unit testing. For each generated Profile class,
there is a corresponding `FakeProfile` class that you can provide work and
personal instances to. For example:

    // Create an instance of the SDK-generated fake connector class. This
    // class lets you control the availability of the profiles, which
    // profile you are now running on.
    private final FakeCrossProfileConnector connector =
      new FakeCrossProfileConnector();

    // Create an instance of your real/fake/mock class for both profiles.
    private final CalendarDatabase personalCalendarDatabase =
      new FakeCalendarDatabase();
    private final CalendarDatabase workCalendarDatabase =
      new FakeCalendarDatabase();

    // Create an instance of the SDK-generated fake profile-aware class.
    private final FakeProfileCalendarDatabase profileCalendarDatabase =
      FakeProfileCalendarDatabase.builder()
        .personal(personalCalendarDatabase)
        .work(workCalendarDatabase)
        .connector(connector)
        .build();

    // Pass profileCalendarDatabase into your classes under test, or set
    // Dagger up to inject the fake automatically.