Make the Semantics code be a service.

Port the tests to use the new interface.
diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart
index 8059138..29fa3e2 100644
--- a/packages/flutter/lib/src/rendering/binding.dart
+++ b/packages/flutter/lib/src/rendering/binding.dart
@@ -7,6 +7,7 @@
 import 'package:flutter/gestures.dart';
 import 'package:flutter/scheduler.dart';
 import 'package:flutter/services.dart';
+import 'package:mojo/core.dart' as core;
 import 'package:sky_services/semantics/semantics.mojom.dart' as mojom;
 
 import 'box.dart';
@@ -26,6 +27,7 @@
     _instance = this;
     ui.window.onMetricsChanged = handleMetricsChanged;
     initRenderView();
+    initSemantics();
     assert(renderView != null);
     assert(() {
       initServiceExtensions();
@@ -41,8 +43,6 @@
     if (renderView == null) {
       renderView = new RenderView();
       renderView.scheduleInitialFrame();
-      if (_semanticsClient != null)
-        renderView.scheduleInitialSemantics();
     }
     handleMetricsChanged(); // configures renderView's metrics
   }
@@ -65,12 +65,11 @@
     renderView.configuration = new ViewConfiguration(size: ui.window.size);
   }
 
-  mojom.SemanticsListener _semanticsClient;
-  void setSemanticsClient(mojom.SemanticsListener client) {
-    assert(_semanticsClient == null);
-    _semanticsClient = client;
-    if (renderView != null)
-      renderView.scheduleInitialSemantics();
+  void initSemantics() {
+    SemanticsNode.onSemanticsEnabled = renderView.scheduleInitialSemantics;
+    provideService(mojom.SemanticsServer.serviceName, (core.MojoMessagePipeEndpoint endpoint) {
+      return new SemanticsServer();
+    });
   }
 
   void _handlePersistentFrameCallback(Duration timeStamp) {
@@ -84,9 +83,9 @@
     RenderObject.flushCompositingBits();
     RenderObject.flushPaint();
     renderView.compositeFrame(); // this sends the bits to the GPU
-    if (_semanticsClient != null) {
+    if (SemanticsNode.hasListeners) {
       RenderObject.flushSemantics();
-      SemanticsNode.sendSemanticsTreeTo(_semanticsClient);
+      SemanticsNode.sendSemanticsTree();
     }
   }
 
diff --git a/packages/flutter/lib/src/rendering/semantics.dart b/packages/flutter/lib/src/rendering/semantics.dart
index 53adf44..ac27b1d 100644
--- a/packages/flutter/lib/src/rendering/semantics.dart
+++ b/packages/flutter/lib/src/rendering/semantics.dart
@@ -333,7 +333,18 @@
     return result;
   }
 
-  static void sendSemanticsTreeTo(mojom.SemanticsListener client) {
+  static List<mojom.SemanticsListener> _listeners;
+  static bool get hasListeners => _listeners != null && _listeners.length > 0;
+  static VoidCallback onSemanticsEnabled; // set by the binding
+  static void addListener(mojom.SemanticsListener listener) {
+    if (!hasListeners)
+      onSemanticsEnabled();
+    _listeners ??= <mojom.SemanticsListener>[];
+    _listeners.add(listener);
+  }
+
+  static void sendSemanticsTree() {
+    assert(hasListeners);
     for (SemanticsNode oldNode in _detachedNodes) {
       // The other side will have forgotten this node if we even send
       // it again, so make sure to mark it dirty so that it'll get
@@ -377,7 +388,8 @@
       if (node._dirty && node.attached)
         updatedNodes.add(node._serialize());
     }
-    client.updateSemanticsTree(updatedNodes);
+    for (mojom.SemanticsListener listener in _listeners)
+      listener.updateSemanticsTree(updatedNodes);
     _dirtyNodes.clear();
   }
 
@@ -428,6 +440,7 @@
 
 class SemanticsServer extends mojom.SemanticsServer {
   void addSemanticsListener(mojom.SemanticsListener listener) {
+    SemanticsNode.addListener(listener);
   }
   void tap(int nodeID) {
     SemanticsNode.getSemanticActionHandlerForId(nodeID, neededFlag: _SemanticFlags.canBeTapped)?.handleSemanticTap();
diff --git a/packages/flutter/lib/src/widgets/semantics_debugger.dart b/packages/flutter/lib/src/widgets/semantics_debugger.dart
index 7616b96..288150b 100644
--- a/packages/flutter/lib/src/widgets/semantics_debugger.dart
+++ b/packages/flutter/lib/src/widgets/semantics_debugger.dart
@@ -31,7 +31,7 @@
   }
   void _update() {
     setState(() {
-      // the generation of the _SemanticsDebuggerClient has changed
+      // the generation of the _SemanticsDebuggerListener has changed
     });
   }
   Point _lastPointerDownLocation;
@@ -214,9 +214,10 @@
 
   _SemanticsDebuggerEntry hitTest(Point position, _SemanticsDebuggerEntryFilter filter) {
     if (transform != null) {
-      if (transform.determinant == 0.0)
+      Matrix4 invertedTransform = new Matrix4.identity();
+      double determinant = invertedTransform.copyInverse(transform);
+      if (determinant == 0.0)
         return null;
-      Matrix4 invertedTransform = new Matrix4.inverted(transform);
       position = MatrixUtils.transformPoint(invertedTransform, position);
     }
     if (!rect.contains(position))
@@ -235,13 +236,12 @@
 
 class _SemanticsDebuggerListener implements mojom.SemanticsListener {
   _SemanticsDebuggerListener._() {
-    Renderer.instance.setSemanticsClient(this);
+    SemanticsNode.addListener(this);
   }
 
   static _SemanticsDebuggerListener instance;
-  static mojom.SemanticsServer _server;
-  static void ensureInstantiated({ mojom.SemanticsServer server }) {
-    _server = server ?? new SemanticsServer();
+  static final SemanticsServer _server = new SemanticsServer();
+  static void ensureInstantiated() {
     instance ??= new _SemanticsDebuggerListener._();
   }
 
diff --git a/packages/flutter/test/rendering/rendering_tester.dart b/packages/flutter/test/rendering/rendering_tester.dart
index 2b620ad..fb700b9 100644
--- a/packages/flutter/test/rendering/rendering_tester.dart
+++ b/packages/flutter/test/rendering/rendering_tester.dart
@@ -26,7 +26,7 @@
   composite
 }
 
-class TestRenderingFlutterBinding extends BindingBase with Scheduler, Renderer, Gesturer {
+class TestRenderingFlutterBinding extends BindingBase with Scheduler, MojoShell, Renderer, Gesturer {
   void initRenderView() {
     if (renderView == null) {
       renderView = new TestRenderView();
diff --git a/packages/flutter/test/widget/test_semantics.dart b/packages/flutter/test/widget/test_semantics.dart
index 6079e93..7eda783 100644
--- a/packages/flutter/test/widget/test_semantics.dart
+++ b/packages/flutter/test/widget/test_semantics.dart
@@ -7,7 +7,7 @@
 
 class TestSemanticsListener implements mojom.SemanticsListener {
   TestSemanticsListener() {
-    Renderer.instance.setSemanticsClient(this);
+    SemanticsNode.addListener(this);
   }
   final List<mojom.SemanticsNode> updates = <mojom.SemanticsNode>[];
   updateSemanticsTree(List<mojom.SemanticsNode> nodes) {