[sessionmgr] Delay initializing services until a SessionShell comes up and connects.

Currently when the sessionmgr starts it initializes all the services the
session shell needs before it launches the session shell.  This causes a
significant delay to the session shell starting as we need to launch
numerous components before it gets to session shell.

This change makes session shell start before any other services and the
other services are started upon session shell first asking for them.

Test: Logged in and gathered metrics with traceutil to see the order of things being launched.

Change-Id: I42a654b874cbc910957eba5975e6befc28b68d03
diff --git a/bin/sessionmgr/sessionmgr_impl.cc b/bin/sessionmgr/sessionmgr_impl.cc
index 1a9470a..a3762bb 100644
--- a/bin/sessionmgr/sessionmgr_impl.cc
+++ b/bin/sessionmgr/sessionmgr_impl.cc
@@ -191,18 +191,35 @@
     fidl::InterfaceHandle<fuchsia::modular::internal::UserContext> user_context,
     fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner>
         view_owner_request) {
+  // This is called in the service connection factory callbacks for session
+  // shell (see how RunSessionShell() initializes session_shell_services_) to
+  // lazily initialize the following services only once they are requested
+  // for the first time.
+  finish_initialization_ = fit::defer<fit::closure>([this,
+        session_shell_url = session_shell.url,
+        ledger_token_manager = std::move(ledger_token_manager),
+        story_shell = std::move(story_shell)] () mutable {
+    InitializeLedger(std::move(ledger_token_manager));
+    InitializeDeviceMap();
+    InitializeMessageQueueManager();
+    InitializeMaxwellAndModular(session_shell_url, std::move(story_shell));
+    ConnectSessionShellToStoryProvider();
+    AtEnd([this](std::function<void()> cont) { TerminateSessionShell(cont); });
+    InitializeClipboard();
+    ReportEvent(ModularEvent::BOOTED_TO_SESSIONMGR);
+  });
+
   InitializeUser(std::move(account), std::move(agent_token_manager),
                  std::move(user_context));
-  InitializeLedger(std::move(ledger_token_manager));
-  InitializeDeviceMap();
-  InitializeMessageQueueManager();
-  InitializeMaxwellAndModular(session_shell.url, std::move(story_shell));
-  InitializeClipboard();
   InitializeSessionShell(
       std::move(session_shell),
       zx::eventpair(view_owner_request.TakeChannel().release()));
+}
 
-  ReportEvent(ModularEvent::BOOTED_TO_SESSIONMGR);
+void SessionmgrImpl::ConnectSessionShellToStoryProvider() {
+  fuchsia::modular::SessionShellPtr session_shell;
+  session_shell_app_->services().ConnectToService(session_shell.NewRequest());
+  story_provider_impl_->SetSessionShell(std::move(session_shell));
 }
 
 void SessionmgrImpl::InitializeUser(
@@ -650,7 +667,6 @@
   session_shell_view_host_ =
       std::make_unique<ViewHost>(std::move(view_context));
   RunSessionShell(std::move(session_shell));
-  AtEnd([this](std::function<void()> cont) { TerminateSessionShell(cont); });
 }
 
 void SessionmgrImpl::RunSessionShell(
@@ -660,20 +676,24 @@
   session_shell_services_.AddService<fuchsia::modular::SessionShellContext>(
       [this](fidl::InterfaceRequest<fuchsia::modular::SessionShellContext>
                  request) {
+        finish_initialization_.call();
         session_shell_context_bindings_.AddBinding(this, std::move(request));
       });
   session_shell_services_.AddService<fuchsia::modular::ComponentContext>(
       [this](
           fidl::InterfaceRequest<fuchsia::modular::ComponentContext> request) {
+        finish_initialization_.call();
         session_shell_component_context_impl_->Connect(std::move(request));
       });
   session_shell_services_.AddService<fuchsia::modular::PuppetMaster>(
       [this](fidl::InterfaceRequest<fuchsia::modular::PuppetMaster> request) {
+        finish_initialization_.call();
         puppet_master_impl_->Connect(std::move(request));
       });
   session_shell_services_.AddService<fuchsia::modular::IntelligenceServices>(
       [this](fidl::InterfaceRequest<fuchsia::modular::IntelligenceServices>
                  request) {
+        finish_initialization_.call();
         fuchsia::modular::ComponentScope component_scope;
         component_scope.set_global_scope(fuchsia::modular::GlobalScope());
         user_intelligence_provider_impl_->GetComponentIntelligenceServices(
@@ -709,10 +729,6 @@
   session_shell_app_->services().ConnectToService(view_provider.NewRequest());
   view_provider->CreateView(view_owner.NewRequest(), nullptr);
   session_shell_view_host_->ConnectView(std::move(view_owner));
-
-  fuchsia::modular::SessionShellPtr session_shell;
-  session_shell_app_->services().ConnectToService(session_shell.NewRequest());
-  story_provider_impl_->SetSessionShell(std::move(session_shell));
 }
 
 void SessionmgrImpl::TerminateSessionShell(const std::function<void()>& done) {
@@ -738,6 +754,7 @@
     sessionmgr_impl_->story_provider_impl_->StopAllStories([this, flow] {
       sessionmgr_impl_->TerminateSessionShell([this, flow] {
         sessionmgr_impl_->RunSessionShell(std::move(session_shell_config_));
+        sessionmgr_impl_->ConnectSessionShellToStoryProvider();
       });
     });
   }
diff --git a/bin/sessionmgr/sessionmgr_impl.h b/bin/sessionmgr/sessionmgr_impl.h
index 5f435a3..3e35fa4 100644
--- a/bin/sessionmgr/sessionmgr_impl.h
+++ b/bin/sessionmgr/sessionmgr_impl.h
@@ -21,6 +21,7 @@
 #include <lib/component/cpp/service_provider_impl.h>
 #include <lib/fidl/cpp/binding.h>
 #include <lib/fidl/cpp/interface_ptr.h>
+#include <lib/fit/defer.h>
 #include <lib/fxl/macros.h>
 #include <zx/eventpair.h>
 
@@ -199,6 +200,8 @@
   // execution steps are stored in at_end_.
   void TerminateRecurse(int i);
 
+  void ConnectSessionShellToStoryProvider();
+
   component::StartupContext* const startup_context_;
   const Options options_;
   std::unique_ptr<scoped_tmpfs::ScopedTmpFS> memfs_for_ledger_;
@@ -302,6 +305,8 @@
 
   OperationQueue operation_queue_;
 
+  fit::deferred_action<fit::closure> finish_initialization_;
+
   FXL_DISALLOW_COPY_AND_ASSIGN(SessionmgrImpl);
 };