Rewrite SchedulerLifecycle, employing a state machine.

This change addresses two issues:
  - Ensure leadership is canceled whenever onDefeated is called.
  - Scheduler should wait for registered to be called before attempting to
    invoke driver.

Some additional structural changes were made:
  - Driver.run() is no longer used.  Instead, we invoke Driver.start()
    (non-blocking), and the lifecycle uses Driver.join() to await exit.
    This allows us to avoid jumping through thread-safety hoops in unit tests.
  - A shim interface (DelayedActions) was added to SchedulerLifecycle to make
    testing easier when capturing delayed closures.

Testing Done:
gradle clean build

Reviewed at https://reviews.apache.org/r/16054/