discovery: a new discovery api (mojo)

  - Rename 'Service' to 'Advertisement'
  - Make 'Update' as an interface

MultiPart: 1/2

Change-Id: I1237608b113532565d80dfbdeee79f56eec651e5
diff --git a/Makefile b/Makefile
index 02700ca..5175e8a 100644
--- a/Makefile
+++ b/Makefile
@@ -10,15 +10,19 @@
 	DISCOVERY_BUILD_DIR := $(CURDIR)/gen/mojo/linux_amd64
 endif
 
+# If this is not the first mojo shell, then you must reuse the dev servers
+# to avoid a "port in use" error.
+#ifneq ($(shell fuser 32000/tcp),)
+ifneq ($(shell netstat -ntl | fgrep 32000 | wc -l),0)
+	REUSE_FLAG := --reuse-servers
+endif
+
 MOJO_SHELL_FLAGS := $(MOJO_SHELL_FLAGS) \
 	--config-alias DISCOVERY_DIR=$(CURDIR) \
 	--config-alias DISCOVERY_BUILD_DIR=$(DISCOVERY_BUILD_DIR) \
+	$(REUSE_FLAG) \
 	$(ORIGIN_FLAG)
 
-define CGO_TEST
-	jiri go --profiles=$(MOJO_PROFILE),base test -v $1
-endef
-
 V23_GO_FILES := $(shell find $(JIRI_ROOT) -name "*.go")
 PYTHONPATH := $(MOJO_SDK)/src/mojo/public/third_party:$(PYTHONPATH)
 
@@ -91,7 +95,7 @@
 	rm -f lib/gen/mojom/$(notdir $@)
 
 discovery-test: $(V23_GO_FILES) go/src/mojom/vanadium/discovery/discovery.mojom.go | mojo-env-check
-	$(call CGO_TEST,vanadium/discovery/internal)
+	$(call MOGO_TEST,-v vanadium/discovery/internal/...)
 
 clean:
 	rm -rf gen
diff --git a/go/src/examples/advertiser/advertiser.go b/go/src/examples/advertiser/advertiser.go
index 0d41e53..d360991 100644
--- a/go/src/examples/advertiser/advertiser.go
+++ b/go/src/examples/advertiser/advertiser.go
@@ -25,21 +25,26 @@
 	req, ptr := discovery.CreateMessagePipeForDiscovery()
 	ctx.ConnectToApplication("https://mojo.v.io/discovery.mojo").ConnectToService(&req)
 
-	service := discovery.Service{
+	ad := discovery.Advertisement{
 		InterfaceName: "v.io/discovery.T",
-		Addrs:         []string{"localhost:1000", "localhost:2000"},
-		Attrs:         &map[string]string{"foo": "bar"},
+		Addresses:     []string{"localhost:1000"},
+		Attributes:    &map[string]string{"foo": "abc"},
+		Attachments:   &map[string][]byte{"bar": []byte{1, 2, 3}},
 	}
-	proxy := discovery.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
-	instanceId, e1, e2 := proxy.StartAdvertising(service, nil)
+	dProxy := discovery.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
+	id, closerPtr, e1, e2 := dProxy.Advertise(ad, nil)
 	if e1 != nil || e2 != nil {
-		log.Println("Error occurred", e1, e2)
+		log.Printf("Failed to advertise: %v, %v", e1, e2)
 		return
 	}
+	log.Printf("Advertising %x...", *id)
 
 	d.stop = func() {
-		proxy.StopAdvertising(instanceId)
-		proxy.Close_Proxy()
+		cProxy := discovery.NewCloserProxy(*closerPtr, bindings.GetAsyncWaiter())
+		cProxy.Close()
+		cProxy.Close_Proxy()
+
+		dProxy.Close_Proxy()
 	}
 }
 
diff --git a/go/src/examples/scanner/scanner.go b/go/src/examples/scanner/scanner.go
index d380ce4..15d6a7f 100644
--- a/go/src/examples/scanner/scanner.go
+++ b/go/src/examples/scanner/scanner.go
@@ -19,15 +19,23 @@
 
 type scanHandler struct{}
 
-func (*scanHandler) Update(update discovery.ScanUpdate) error {
-	var tag string
-	switch update.UpdateType {
-	case discovery.UpdateType_Found:
-		tag = "Found"
-	case discovery.UpdateType_Lost:
+func (*scanHandler) OnUpdate(ptr discovery.Update_Pointer) error {
+	uProxy := discovery.NewUpdateProxy(ptr, bindings.GetAsyncWaiter())
+	defer uProxy.Close_Proxy()
+
+	tag := "Found"
+	if lost, _ := uProxy.IsLost(); lost {
 		tag = "Lost"
 	}
-	log.Printf("%s service: %v", tag, update.Service)
+	id, _ := uProxy.GetId()
+	interfaceName, _ := uProxy.GetInterfaceName()
+	addresses, _ := uProxy.GetAddresses()
+	attribute, _ := uProxy.GetAttribute("foo")
+	attachmentHandle, _ := uProxy.GetAttachment("bar")
+	_, attachment := attachmentHandle.ReadData(system.MOJO_READ_DATA_FLAG_NONE)
+	attachmentHandle.Close()
+
+	log.Printf("%s %x: {InterfaceName: %q, Addresses: %q, Attribute[\"foo\"]: %q, Attachment[\"bar\"]: 0x%x}", tag, id, interfaceName, addresses, attribute, attachment)
 	return nil
 }
 
@@ -42,20 +50,15 @@
 	scanHandlerReq, scanHandlerPtr := discovery.CreateMessagePipeForScanHandler()
 	scanHandlerStub := discovery.NewScanHandlerStub(scanHandlerReq, &scanHandler{}, bindings.GetAsyncWaiter())
 
-	proxy := discovery.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
-	scanId, e1, e2 := proxy.StartScan(`v.InterfaceName="v.io/discovery.T"`, scanHandlerPtr)
+	dProxy := discovery.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
+	closerPtr, e1, e2 := dProxy.Scan(`v.InterfaceName="v.io/discovery.T"`, scanHandlerPtr)
 	if e1 != nil || e2 != nil {
-		log.Println("Error occurred", e1, e2)
+		log.Printf("Failed to scan: %v, %v", e1, e2)
 		scanHandlerStub.Close()
+		dProxy.Close_Proxy()
 		return
 	}
 
-	d.stop = func() {
-		proxy.StopScan(scanId)
-		scanHandlerStub.Close()
-		proxy.Close_Proxy()
-	}
-
 	go func() {
 		for {
 			if err := scanHandlerStub.ServeRequest(); err != nil {
@@ -67,6 +70,15 @@
 			}
 		}
 	}()
+
+	d.stop = func() {
+		cProxy := discovery.NewCloserProxy(*closerPtr, bindings.GetAsyncWaiter())
+		cProxy.Close()
+		cProxy.Close_Proxy()
+
+		scanHandlerStub.Close()
+		dProxy.Close_Proxy()
+	}
 }
 
 func (*delegate) AcceptConnection(connection *application.Connection) {
diff --git a/go/src/mojom/vanadium/discovery/discovery.mojom.go b/go/src/mojom/vanadium/discovery/discovery.mojom.go
index 3d65012..f4da926 100644
--- a/go/src/mojom/vanadium/discovery/discovery.mojom.go
+++ b/go/src/mojom/vanadium/discovery/discovery.mojom.go
@@ -19,18 +19,9 @@
 	sort "sort"
 )
 
-type UpdateType int32
-
-const (
-	UpdateType_Found = 1
-	UpdateType_Lost  = UpdateType_Found + 1
-)
-
 type Discovery interface {
-	StartAdvertising(inService Service, inVisibility *[]string) (outInstanceId string, outErr *Error, err error)
-	StopAdvertising(inInstanceId string) (outErr *Error, err error)
-	StartScan(inQuery string, inHandler ScanHandler_Pointer) (outScanId uint32, outErr *Error, err error)
-	StopScan(inScanId uint32) (outErr *Error, err error)
+	Advertise(inAd Advertisement, inVisibility *[]string) (outInstanceId *[16]uint8, outCloser *Closer_Pointer, outErr *Error, err error)
+	Scan(inQuery string, inHandler ScanHandler_Pointer) (outCloser *Closer_Pointer, outErr *Error, err error)
 }
 
 var discovery_Name = "v23::discovery::Discovery"
@@ -75,10 +66,8 @@
 	return Discovery_Request(r), Discovery_Pointer(p)
 }
 
-const discovery_StartAdvertising_Name uint32 = 0
-const discovery_StopAdvertising_Name uint32 = 1
-const discovery_StartScan_Name uint32 = 2
-const discovery_StopScan_Name uint32 = 3
+const discovery_Advertise_Name uint32 = 0
+const discovery_Scan_Name uint32 = 1
 
 type Discovery_Proxy struct {
 	router *bindings.Router
@@ -96,17 +85,17 @@
 	p.router.Close()
 }
 
-type discovery_StartAdvertising_Params struct {
-	inService    Service
+type discovery_Advertise_Params struct {
+	inAd         Advertisement
 	inVisibility *[]string
 }
 
-func (s *discovery_StartAdvertising_Params) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_Advertise_Params) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(16, 0)
 	if err := encoder.WritePointer(); err != nil {
 		return err
 	}
-	if err := s.inService.Encode(encoder); err != nil {
+	if err := s.inAd.Encode(encoder); err != nil {
 		return err
 	}
 	if s.inVisibility == nil {
@@ -134,23 +123,23 @@
 	return nil
 }
 
-var discovery_StartAdvertising_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_Advertise_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{24, 0},
 }
 
-func (s *discovery_StartAdvertising_Params) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_Advertise_Params) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(discovery_StartAdvertising_Params_Versions), func(i int) bool {
-		return discovery_StartAdvertising_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_Advertise_Params_Versions), func(i int) bool {
+		return discovery_Advertise_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(discovery_StartAdvertising_Params_Versions) {
-		if discovery_StartAdvertising_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_Advertise_Params_Versions) {
+		if discovery_Advertise_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := discovery_StartAdvertising_Params_Versions[index].Size
+		expectedSize := discovery_Advertise_Params_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -165,7 +154,7 @@
 		if pointer0 == 0 {
 			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
 		} else {
-			if err := s.inService.Decode(decoder); err != nil {
+			if err := s.inAd.Decode(decoder); err != nil {
 				return err
 			}
 		}
@@ -210,18 +199,36 @@
 	return nil
 }
 
-type discovery_StartAdvertising_ResponseParams struct {
-	outInstanceId string
+type discovery_Advertise_ResponseParams struct {
+	outInstanceId *[16]uint8
+	outCloser     *Closer_Pointer
 	outErr        *Error
 }
 
-func (s *discovery_StartAdvertising_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
+func (s *discovery_Advertise_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(24, 0)
+	if s.outInstanceId == nil {
+		encoder.WriteNullPointer()
+	} else {
+		if err := encoder.WritePointer(); err != nil {
+			return err
+		}
+		encoder.StartArray(uint32(len((*s.outInstanceId))), 8)
+		for _, elem0 := range *s.outInstanceId {
+			if err := encoder.WriteUint8(elem0); err != nil {
+				return err
+			}
+		}
+		if err := encoder.Finish(); err != nil {
+			return err
+		}
 	}
-	if err := encoder.WriteString(s.outInstanceId); err != nil {
-		return err
+	if s.outCloser == nil {
+		encoder.WriteInvalidInterface()
+	} else {
+		if err := encoder.WriteInterface((*s.outCloser).PassMessagePipe()); err != nil {
+			return err
+		}
 	}
 	if s.outErr == nil {
 		encoder.WriteNullPointer()
@@ -239,23 +246,23 @@
 	return nil
 }
 
-var discovery_StartAdvertising_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
+var discovery_Advertise_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{32, 0},
 }
 
-func (s *discovery_StartAdvertising_ResponseParams) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_Advertise_ResponseParams) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(discovery_StartAdvertising_ResponseParams_Versions), func(i int) bool {
-		return discovery_StartAdvertising_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_Advertise_ResponseParams_Versions), func(i int) bool {
+		return discovery_Advertise_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(discovery_StartAdvertising_ResponseParams_Versions) {
-		if discovery_StartAdvertising_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_Advertise_ResponseParams_Versions) {
+		if discovery_Advertise_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := discovery_StartAdvertising_ResponseParams_Versions[index].Size
+		expectedSize := discovery_Advertise_ResponseParams_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -268,13 +275,40 @@
 			return err
 		}
 		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+			s.outInstanceId = nil
 		} else {
-			value0, err := decoder.ReadString()
+			s.outInstanceId = new([16]uint8)
+			len0, err := decoder.StartArray(8)
 			if err != nil {
 				return err
 			}
-			s.outInstanceId = value0
+			if len0 != 16 {
+				return &bindings.ValidationError{bindings.UnexpectedArrayHeader,
+					fmt.Sprintf("invalid array length: expected %d, got %d", 16, len0),
+				}
+			}
+			for i0 := uint32(0); i0 < len0; i0++ {
+				value1, err := decoder.ReadUint8()
+				if err != nil {
+					return err
+				}
+				(*s.outInstanceId)[i0] = value1
+			}
+			if err := decoder.Finish(); err != nil {
+				return err
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		handle0, err := decoder.ReadInterface()
+		if err != nil {
+			return err
+		}
+		if handle0.IsValid() {
+			handleOwner := bindings.NewMessagePipeHandleOwner(handle0)
+			s.outCloser = &Closer_Pointer{handleOwner}
+		} else {
+			s.outCloser = nil
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
@@ -297,13 +331,13 @@
 	return nil
 }
 
-func (p *Discovery_Proxy) StartAdvertising(inService Service, inVisibility *[]string) (outInstanceId string, outErr *Error, err error) {
-	payload := &discovery_StartAdvertising_Params{
-		inService,
+func (p *Discovery_Proxy) Advertise(inAd Advertisement, inVisibility *[]string) (outInstanceId *[16]uint8, outCloser *Closer_Pointer, outErr *Error, err error) {
+	payload := &discovery_Advertise_Params{
+		inAd,
 		inVisibility,
 	}
 	header := bindings.MessageHeader{
-		Type:      discovery_StartAdvertising_Name,
+		Type:      discovery_Advertise_Name,
 		Flags:     bindings.MessageExpectsResponseFlag,
 		RequestId: p.ids.Count(),
 	}
@@ -324,196 +358,29 @@
 		}
 		return
 	}
-	if got, want := readResult.Message.Header.Type, discovery_StartAdvertising_Name; got != want {
+	if got, want := readResult.Message.Header.Type, discovery_Advertise_Name; got != want {
 		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
 			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
 		}
 		return
 	}
-	var response discovery_StartAdvertising_ResponseParams
+	var response discovery_Advertise_ResponseParams
 	if err = readResult.Message.DecodePayload(&response); err != nil {
 		p.Close_Proxy()
 		return
 	}
 	outInstanceId = response.outInstanceId
+	outCloser = response.outCloser
 	outErr = response.outErr
 	return
 }
 
-type discovery_StopAdvertising_Params struct {
-	inInstanceId string
-}
-
-func (s *discovery_StopAdvertising_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inInstanceId); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var discovery_StopAdvertising_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *discovery_StopAdvertising_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(discovery_StopAdvertising_Params_Versions), func(i int) bool {
-		return discovery_StopAdvertising_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(discovery_StopAdvertising_Params_Versions) {
-		if discovery_StopAdvertising_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := discovery_StopAdvertising_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inInstanceId = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type discovery_StopAdvertising_ResponseParams struct {
-	outErr *Error
-}
-
-func (s *discovery_StopAdvertising_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if s.outErr == nil {
-		encoder.WriteNullPointer()
-	} else {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := (*s.outErr).Encode(encoder); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var discovery_StopAdvertising_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *discovery_StopAdvertising_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(discovery_StopAdvertising_ResponseParams_Versions), func(i int) bool {
-		return discovery_StopAdvertising_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(discovery_StopAdvertising_ResponseParams_Versions) {
-		if discovery_StopAdvertising_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := discovery_StopAdvertising_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			s.outErr = nil
-		} else {
-			s.outErr = new(Error)
-			if err := (*s.outErr).Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Discovery_Proxy) StopAdvertising(inInstanceId string) (outErr *Error, err error) {
-	payload := &discovery_StopAdvertising_Params{
-		inInstanceId,
-	}
-	header := bindings.MessageHeader{
-		Type:      discovery_StopAdvertising_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, discovery_StopAdvertising_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response discovery_StopAdvertising_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type discovery_StartScan_Params struct {
+type discovery_Scan_Params struct {
 	inQuery   string
 	inHandler ScanHandler_Pointer
 }
 
-func (s *discovery_StartScan_Params) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_Scan_Params) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(16, 0)
 	if err := encoder.WritePointer(); err != nil {
 		return err
@@ -530,23 +397,23 @@
 	return nil
 }
 
-var discovery_StartScan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_Scan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{24, 0},
 }
 
-func (s *discovery_StartScan_Params) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_Scan_Params) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(discovery_StartScan_Params_Versions), func(i int) bool {
-		return discovery_StartScan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_Scan_Params_Versions), func(i int) bool {
+		return discovery_Scan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(discovery_StartScan_Params_Versions) {
-		if discovery_StartScan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_Scan_Params_Versions) {
+		if discovery_Scan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := discovery_StartScan_Params_Versions[index].Size
+		expectedSize := discovery_Scan_Params_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -586,15 +453,19 @@
 	return nil
 }
 
-type discovery_StartScan_ResponseParams struct {
-	outScanId uint32
+type discovery_Scan_ResponseParams struct {
+	outCloser *Closer_Pointer
 	outErr    *Error
 }
 
-func (s *discovery_StartScan_ResponseParams) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_Scan_ResponseParams) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(16, 0)
-	if err := encoder.WriteUint32(s.outScanId); err != nil {
-		return err
+	if s.outCloser == nil {
+		encoder.WriteInvalidInterface()
+	} else {
+		if err := encoder.WriteInterface((*s.outCloser).PassMessagePipe()); err != nil {
+			return err
+		}
 	}
 	if s.outErr == nil {
 		encoder.WriteNullPointer()
@@ -612,23 +483,23 @@
 	return nil
 }
 
-var discovery_StartScan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_Scan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{24, 0},
 }
 
-func (s *discovery_StartScan_ResponseParams) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_Scan_ResponseParams) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(discovery_StartScan_ResponseParams_Versions), func(i int) bool {
-		return discovery_StartScan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_Scan_ResponseParams_Versions), func(i int) bool {
+		return discovery_Scan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(discovery_StartScan_ResponseParams_Versions) {
-		if discovery_StartScan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_Scan_ResponseParams_Versions) {
+		if discovery_Scan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := discovery_StartScan_ResponseParams_Versions[index].Size
+		expectedSize := discovery_Scan_ResponseParams_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -636,11 +507,16 @@
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadUint32()
+		handle0, err := decoder.ReadInterface()
 		if err != nil {
 			return err
 		}
-		s.outScanId = value0
+		if handle0.IsValid() {
+			handleOwner := bindings.NewMessagePipeHandleOwner(handle0)
+			s.outCloser = &Closer_Pointer{handleOwner}
+		} else {
+			s.outCloser = nil
+		}
 	}
 	if header.ElementsOrVersion >= 0 {
 		pointer0, err := decoder.ReadPointer()
@@ -662,13 +538,13 @@
 	return nil
 }
 
-func (p *Discovery_Proxy) StartScan(inQuery string, inHandler ScanHandler_Pointer) (outScanId uint32, outErr *Error, err error) {
-	payload := &discovery_StartScan_Params{
+func (p *Discovery_Proxy) Scan(inQuery string, inHandler ScanHandler_Pointer) (outCloser *Closer_Pointer, outErr *Error, err error) {
+	payload := &discovery_Scan_Params{
 		inQuery,
 		inHandler,
 	}
 	header := bindings.MessageHeader{
-		Type:      discovery_StartScan_Name,
+		Type:      discovery_Scan_Name,
 		Flags:     bindings.MessageExpectsResponseFlag,
 		RequestId: p.ids.Count(),
 	}
@@ -689,175 +565,18 @@
 		}
 		return
 	}
-	if got, want := readResult.Message.Header.Type, discovery_StartScan_Name; got != want {
+	if got, want := readResult.Message.Header.Type, discovery_Scan_Name; got != want {
 		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
 			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
 		}
 		return
 	}
-	var response discovery_StartScan_ResponseParams
+	var response discovery_Scan_ResponseParams
 	if err = readResult.Message.DecodePayload(&response); err != nil {
 		p.Close_Proxy()
 		return
 	}
-	outScanId = response.outScanId
-	outErr = response.outErr
-	return
-}
-
-type discovery_StopScan_Params struct {
-	inScanId uint32
-}
-
-func (s *discovery_StopScan_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WriteUint32(s.inScanId); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var discovery_StopScan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *discovery_StopScan_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(discovery_StopScan_Params_Versions), func(i int) bool {
-		return discovery_StopScan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(discovery_StopScan_Params_Versions) {
-		if discovery_StopScan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := discovery_StopScan_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadUint32()
-		if err != nil {
-			return err
-		}
-		s.inScanId = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type discovery_StopScan_ResponseParams struct {
-	outErr *Error
-}
-
-func (s *discovery_StopScan_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if s.outErr == nil {
-		encoder.WriteNullPointer()
-	} else {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := (*s.outErr).Encode(encoder); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var discovery_StopScan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *discovery_StopScan_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(discovery_StopScan_ResponseParams_Versions), func(i int) bool {
-		return discovery_StopScan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(discovery_StopScan_ResponseParams_Versions) {
-		if discovery_StopScan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := discovery_StopScan_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			s.outErr = nil
-		} else {
-			s.outErr = new(Error)
-			if err := (*s.outErr).Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Discovery_Proxy) StopScan(inScanId uint32) (outErr *Error, err error) {
-	payload := &discovery_StopScan_Params{
-		inScanId,
-	}
-	header := bindings.MessageHeader{
-		Type:      discovery_StopScan_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, discovery_StopScan_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response discovery_StopScan_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
+	outCloser = response.outCloser
 	outErr = response.outErr
 	return
 }
@@ -897,23 +616,23 @@
 
 func (s *discovery_Stub) Accept(message *bindings.Message) (err error) {
 	switch message.Header.Type {
-	case discovery_StartAdvertising_Name:
+	case discovery_Advertise_Name:
 		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
 			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
 				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
 			}
 		}
-		var request discovery_StartAdvertising_Params
+		var request discovery_Advertise_Params
 		if err := message.DecodePayload(&request); err != nil {
 			return err
 		}
-		var response discovery_StartAdvertising_ResponseParams
-		response.outInstanceId, response.outErr, err = s.impl.StartAdvertising(request.inService, request.inVisibility)
+		var response discovery_Advertise_ResponseParams
+		response.outInstanceId, response.outCloser, response.outErr, err = s.impl.Advertise(request.inAd, request.inVisibility)
 		if err != nil {
 			return
 		}
 		header := bindings.MessageHeader{
-			Type:      discovery_StartAdvertising_Name,
+			Type:      discovery_Advertise_Name,
 			Flags:     bindings.MessageIsResponseFlag,
 			RequestId: message.Header.RequestId,
 		}
@@ -922,23 +641,23 @@
 			return err
 		}
 		return s.connector.WriteMessage(message)
-	case discovery_StopAdvertising_Name:
+	case discovery_Scan_Name:
 		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
 			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
 				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
 			}
 		}
-		var request discovery_StopAdvertising_Params
+		var request discovery_Scan_Params
 		if err := message.DecodePayload(&request); err != nil {
 			return err
 		}
-		var response discovery_StopAdvertising_ResponseParams
-		response.outErr, err = s.impl.StopAdvertising(request.inInstanceId)
+		var response discovery_Scan_ResponseParams
+		response.outCloser, response.outErr, err = s.impl.Scan(request.inQuery, request.inHandler)
 		if err != nil {
 			return
 		}
 		header := bindings.MessageHeader{
-			Type:      discovery_StopAdvertising_Name,
+			Type:      discovery_Scan_Name,
 			Flags:     bindings.MessageIsResponseFlag,
 			RequestId: message.Header.RequestId,
 		}
@@ -947,48 +666,235 @@
 			return err
 		}
 		return s.connector.WriteMessage(message)
-	case discovery_StartScan_Name:
+	default:
+		return &bindings.ValidationError{
+			bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("unknown method %v", message.Header.Type),
+		}
+	}
+	return
+}
+
+type Closer interface {
+	Close() (err error)
+}
+
+type Closer_Request bindings.InterfaceRequest
+
+type Closer_Pointer bindings.InterfacePointer
+
+type Closer_ServiceFactory struct {
+	Delegate Closer_Factory
+}
+
+type Closer_Factory interface {
+	Create(request Closer_Request)
+}
+
+func (f *Closer_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
+	return &Closer_ServiceDescription{}
+}
+
+func (f *Closer_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
+	request := Closer_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
+	f.Delegate.Create(request)
+}
+
+// CreateMessagePipeForCloser creates a message pipe for use with the
+// Closer interface with a Closer_Request on one end and a Closer_Pointer on the other.
+func CreateMessagePipeForCloser() (Closer_Request, Closer_Pointer) {
+	r, p := bindings.CreateMessagePipeForMojoInterface()
+	return Closer_Request(r), Closer_Pointer(p)
+}
+
+const closer_Close_Name uint32 = 0
+
+type Closer_Proxy struct {
+	router *bindings.Router
+	ids    bindings.Counter
+}
+
+func NewCloserProxy(p Closer_Pointer, waiter bindings.AsyncWaiter) *Closer_Proxy {
+	return &Closer_Proxy{
+		bindings.NewRouter(p.PassMessagePipe(), waiter),
+		bindings.NewCounter(),
+	}
+}
+
+func (p *Closer_Proxy) Close_Proxy() {
+	p.router.Close()
+}
+
+type closer_Close_Params struct {
+}
+
+func (s *closer_Close_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(0, 0)
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var closer_Close_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{8, 0},
+}
+
+func (s *closer_Close_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(closer_Close_Params_Versions), func(i int) bool {
+		return closer_Close_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(closer_Close_Params_Versions) {
+		if closer_Close_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := closer_Close_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type closer_Close_ResponseParams struct {
+}
+
+func (s *closer_Close_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(0, 0)
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var closer_Close_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{8, 0},
+}
+
+func (s *closer_Close_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(closer_Close_ResponseParams_Versions), func(i int) bool {
+		return closer_Close_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(closer_Close_ResponseParams_Versions) {
+		if closer_Close_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := closer_Close_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Closer_Proxy) Close() (err error) {
+	payload := &closer_Close_Params{}
+	header := bindings.MessageHeader{
+		Type:      closer_Close_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, closer_Close_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response closer_Close_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	return
+}
+
+type closer_Stub struct {
+	connector *bindings.Connector
+	impl      Closer
+}
+
+func NewCloserStub(r Closer_Request, impl Closer, waiter bindings.AsyncWaiter) *bindings.Stub {
+	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
+	return bindings.NewStub(connector, &closer_Stub{connector, impl})
+}
+
+func (f *Closer_Request) ServiceDescription() service_describer.ServiceDescription {
+	return &Closer_ServiceDescription{}
+}
+
+type Closer_ServiceDescription struct{}
+
+func (sd *Closer_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
+	err = fmt.Errorf("GetTopLevelInterface not implemented")
+	return
+}
+
+func (sd *Closer_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
+	err = fmt.Errorf("GetTypeDefinition not implemented")
+	return
+}
+
+func (sd *Closer_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
+	err = fmt.Errorf("GetAllTypeDefinitions not implemented")
+	return
+}
+
+var _ service_describer.ServiceDescription = (*Closer_ServiceDescription)(nil)
+
+func (s *closer_Stub) Accept(message *bindings.Message) (err error) {
+	switch message.Header.Type {
+	case closer_Close_Name:
 		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
 			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
 				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
 			}
 		}
-		var request discovery_StartScan_Params
+		var request closer_Close_Params
 		if err := message.DecodePayload(&request); err != nil {
 			return err
 		}
-		var response discovery_StartScan_ResponseParams
-		response.outScanId, response.outErr, err = s.impl.StartScan(request.inQuery, request.inHandler)
+		var response closer_Close_ResponseParams
+		err = s.impl.Close()
 		if err != nil {
 			return
 		}
 		header := bindings.MessageHeader{
-			Type:      discovery_StartScan_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case discovery_StopScan_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request discovery_StopScan_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response discovery_StopScan_ResponseParams
-		response.outErr, err = s.impl.StopScan(request.inScanId)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      discovery_StopScan_Name,
+			Type:      closer_Close_Name,
 			Flags:     bindings.MessageIsResponseFlag,
 			RequestId: message.Header.RequestId,
 		}
@@ -1007,23 +913,13 @@
 }
 
 type ScanHandler interface {
-	Update(inUpdate ScanUpdate) (err error)
+	OnUpdate(inUpdate Update_Pointer) (err error)
 }
 
-var scanHandler_Name = "v23::discovery::ScanHandler"
-
 type ScanHandler_Request bindings.InterfaceRequest
 
-func (r *ScanHandler_Request) Name() string {
-	return scanHandler_Name
-}
-
 type ScanHandler_Pointer bindings.InterfacePointer
 
-func (p *ScanHandler_Pointer) Name() string {
-	return scanHandler_Name
-}
-
 type ScanHandler_ServiceFactory struct {
 	Delegate ScanHandler_Factory
 }
@@ -1032,10 +928,6 @@
 	Create(request ScanHandler_Request)
 }
 
-func (f *ScanHandler_ServiceFactory) Name() string {
-	return scanHandler_Name
-}
-
 func (f *ScanHandler_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
 	return &ScanHandler_ServiceDescription{}
 }
@@ -1052,7 +944,7 @@
 	return ScanHandler_Request(r), ScanHandler_Pointer(p)
 }
 
-const scanHandler_Update_Name uint32 = 0
+const scanHandler_OnUpdate_Name uint32 = 0
 
 type ScanHandler_Proxy struct {
 	router *bindings.Router
@@ -1070,16 +962,13 @@
 	p.router.Close()
 }
 
-type scanHandler_Update_Params struct {
-	inUpdate ScanUpdate
+type scanHandler_OnUpdate_Params struct {
+	inUpdate Update_Pointer
 }
 
-func (s *scanHandler_Update_Params) Encode(encoder *bindings.Encoder) error {
+func (s *scanHandler_OnUpdate_Params) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inUpdate.Encode(encoder); err != nil {
+	if err := encoder.WriteInterface(s.inUpdate.PassMessagePipe()); err != nil {
 		return err
 	}
 	if err := encoder.Finish(); err != nil {
@@ -1088,23 +977,23 @@
 	return nil
 }
 
-var scanHandler_Update_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+var scanHandler_OnUpdate_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{16, 0},
 }
 
-func (s *scanHandler_Update_Params) Decode(decoder *bindings.Decoder) error {
+func (s *scanHandler_OnUpdate_Params) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(scanHandler_Update_Params_Versions), func(i int) bool {
-		return scanHandler_Update_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(scanHandler_OnUpdate_Params_Versions), func(i int) bool {
+		return scanHandler_OnUpdate_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(scanHandler_Update_Params_Versions) {
-		if scanHandler_Update_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(scanHandler_OnUpdate_Params_Versions) {
+		if scanHandler_OnUpdate_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := scanHandler_Update_Params_Versions[index].Size
+		expectedSize := scanHandler_OnUpdate_Params_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -1112,16 +1001,15 @@
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
+		handle0, err := decoder.ReadInterface()
 		if err != nil {
 			return err
 		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		if handle0.IsValid() {
+			handleOwner := bindings.NewMessagePipeHandleOwner(handle0)
+			s.inUpdate = Update_Pointer{handleOwner}
 		} else {
-			if err := s.inUpdate.Decode(decoder); err != nil {
-				return err
-			}
+			return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"}
 		}
 	}
 	if err := decoder.Finish(); err != nil {
@@ -1130,12 +1018,12 @@
 	return nil
 }
 
-func (p *ScanHandler_Proxy) Update(inUpdate ScanUpdate) (err error) {
-	payload := &scanHandler_Update_Params{
+func (p *ScanHandler_Proxy) OnUpdate(inUpdate Update_Pointer) (err error) {
+	payload := &scanHandler_OnUpdate_Params{
 		inUpdate,
 	}
 	header := bindings.MessageHeader{
-		Type:  scanHandler_Update_Name,
+		Type:  scanHandler_OnUpdate_Name,
 		Flags: bindings.MessageNoFlag,
 	}
 	var message *bindings.Message
@@ -1186,17 +1074,17 @@
 
 func (s *scanHandler_Stub) Accept(message *bindings.Message) (err error) {
 	switch message.Header.Type {
-	case scanHandler_Update_Name:
+	case scanHandler_OnUpdate_Name:
 		if message.Header.Flags != bindings.MessageNoFlag {
 			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
 				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
 			}
 		}
-		var request scanHandler_Update_Params
+		var request scanHandler_OnUpdate_Params
 		if err := message.DecodePayload(&request); err != nil {
 			return err
 		}
-		err = s.impl.Update(request.inUpdate)
+		err = s.impl.OnUpdate(request.inUpdate)
 		if err != nil {
 			return
 		}
@@ -1209,34 +1097,1372 @@
 	return
 }
 
-type Service struct {
-	InstanceId    *string
-	InstanceName  *string
-	InterfaceName string
-	Attrs         *map[string]string
-	Addrs         []string
-	Attachments   *map[string][]uint8
+type Update interface {
+	IsLost() (outLost bool, err error)
+	GetId() (outId [16]uint8, err error)
+	GetInterfaceName() (outInterfaceName string, err error)
+	GetAddresses() (outAddresses []string, err error)
+	GetAttribute(inName string) (outAttribute string, err error)
+	GetAttachment(inName string) (outData system.ConsumerHandle, err error)
+	GetAdvertisement() (outAd Advertisement, err error)
 }
 
-func (s *Service) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(48, 0)
-	if s.InstanceId == nil {
-		encoder.WriteNullPointer()
-	} else {
-		if err := encoder.WritePointer(); err != nil {
+type Update_Request bindings.InterfaceRequest
+
+type Update_Pointer bindings.InterfacePointer
+
+type Update_ServiceFactory struct {
+	Delegate Update_Factory
+}
+
+type Update_Factory interface {
+	Create(request Update_Request)
+}
+
+func (f *Update_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
+	return &Update_ServiceDescription{}
+}
+
+func (f *Update_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
+	request := Update_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
+	f.Delegate.Create(request)
+}
+
+// CreateMessagePipeForUpdate creates a message pipe for use with the
+// Update interface with a Update_Request on one end and a Update_Pointer on the other.
+func CreateMessagePipeForUpdate() (Update_Request, Update_Pointer) {
+	r, p := bindings.CreateMessagePipeForMojoInterface()
+	return Update_Request(r), Update_Pointer(p)
+}
+
+const update_IsLost_Name uint32 = 0
+const update_GetId_Name uint32 = 1
+const update_GetInterfaceName_Name uint32 = 2
+const update_GetAddresses_Name uint32 = 3
+const update_GetAttribute_Name uint32 = 4
+const update_GetAttachment_Name uint32 = 5
+const update_GetAdvertisement_Name uint32 = 6
+
+type Update_Proxy struct {
+	router *bindings.Router
+	ids    bindings.Counter
+}
+
+func NewUpdateProxy(p Update_Pointer, waiter bindings.AsyncWaiter) *Update_Proxy {
+	return &Update_Proxy{
+		bindings.NewRouter(p.PassMessagePipe(), waiter),
+		bindings.NewCounter(),
+	}
+}
+
+func (p *Update_Proxy) Close_Proxy() {
+	p.router.Close()
+}
+
+type update_IsLost_Params struct {
+}
+
+func (s *update_IsLost_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(0, 0)
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_IsLost_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{8, 0},
+}
+
+func (s *update_IsLost_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_IsLost_Params_Versions), func(i int) bool {
+		return update_IsLost_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_IsLost_Params_Versions) {
+		if update_IsLost_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_IsLost_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type update_IsLost_ResponseParams struct {
+	outLost bool
+}
+
+func (s *update_IsLost_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WriteBool(s.outLost); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_IsLost_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_IsLost_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_IsLost_ResponseParams_Versions), func(i int) bool {
+		return update_IsLost_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_IsLost_ResponseParams_Versions) {
+		if update_IsLost_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_IsLost_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		value0, err := decoder.ReadBool()
+		if err != nil {
 			return err
 		}
-		if err := encoder.WriteString((*s.InstanceId)); err != nil {
+		s.outLost = value0
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Update_Proxy) IsLost() (outLost bool, err error) {
+	payload := &update_IsLost_Params{}
+	header := bindings.MessageHeader{
+		Type:      update_IsLost_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, update_IsLost_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response update_IsLost_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	outLost = response.outLost
+	return
+}
+
+type update_GetId_Params struct {
+}
+
+func (s *update_GetId_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(0, 0)
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetId_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{8, 0},
+}
+
+func (s *update_GetId_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetId_Params_Versions), func(i int) bool {
+		return update_GetId_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetId_Params_Versions) {
+		if update_GetId_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetId_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type update_GetId_ResponseParams struct {
+	outId [16]uint8
+}
+
+func (s *update_GetId_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	encoder.StartArray(uint32(len(s.outId)), 8)
+	for _, elem0 := range s.outId {
+		if err := encoder.WriteUint8(elem0); err != nil {
 			return err
 		}
 	}
-	if s.InstanceName == nil {
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetId_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetId_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetId_ResponseParams_Versions), func(i int) bool {
+		return update_GetId_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetId_ResponseParams_Versions) {
+		if update_GetId_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetId_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			len0, err := decoder.StartArray(8)
+			if err != nil {
+				return err
+			}
+			if len0 != 16 {
+				return &bindings.ValidationError{bindings.UnexpectedArrayHeader,
+					fmt.Sprintf("invalid array length: expected %d, got %d", 16, len0),
+				}
+			}
+			for i0 := uint32(0); i0 < len0; i0++ {
+				value1, err := decoder.ReadUint8()
+				if err != nil {
+					return err
+				}
+				s.outId[i0] = value1
+			}
+			if err := decoder.Finish(); err != nil {
+				return err
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Update_Proxy) GetId() (outId [16]uint8, err error) {
+	payload := &update_GetId_Params{}
+	header := bindings.MessageHeader{
+		Type:      update_GetId_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, update_GetId_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response update_GetId_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	outId = response.outId
+	return
+}
+
+type update_GetInterfaceName_Params struct {
+}
+
+func (s *update_GetInterfaceName_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(0, 0)
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetInterfaceName_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{8, 0},
+}
+
+func (s *update_GetInterfaceName_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetInterfaceName_Params_Versions), func(i int) bool {
+		return update_GetInterfaceName_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetInterfaceName_Params_Versions) {
+		if update_GetInterfaceName_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetInterfaceName_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type update_GetInterfaceName_ResponseParams struct {
+	outInterfaceName string
+}
+
+func (s *update_GetInterfaceName_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	if err := encoder.WriteString(s.outInterfaceName); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetInterfaceName_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetInterfaceName_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetInterfaceName_ResponseParams_Versions), func(i int) bool {
+		return update_GetInterfaceName_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetInterfaceName_ResponseParams_Versions) {
+		if update_GetInterfaceName_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetInterfaceName_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			value0, err := decoder.ReadString()
+			if err != nil {
+				return err
+			}
+			s.outInterfaceName = value0
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Update_Proxy) GetInterfaceName() (outInterfaceName string, err error) {
+	payload := &update_GetInterfaceName_Params{}
+	header := bindings.MessageHeader{
+		Type:      update_GetInterfaceName_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, update_GetInterfaceName_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response update_GetInterfaceName_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	outInterfaceName = response.outInterfaceName
+	return
+}
+
+type update_GetAddresses_Params struct {
+}
+
+func (s *update_GetAddresses_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(0, 0)
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAddresses_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{8, 0},
+}
+
+func (s *update_GetAddresses_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAddresses_Params_Versions), func(i int) bool {
+		return update_GetAddresses_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAddresses_Params_Versions) {
+		if update_GetAddresses_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAddresses_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type update_GetAddresses_ResponseParams struct {
+	outAddresses []string
+}
+
+func (s *update_GetAddresses_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	encoder.StartArray(uint32(len(s.outAddresses)), 64)
+	for _, elem0 := range s.outAddresses {
+		if err := encoder.WritePointer(); err != nil {
+			return err
+		}
+		if err := encoder.WriteString(elem0); err != nil {
+			return err
+		}
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAddresses_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetAddresses_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAddresses_ResponseParams_Versions), func(i int) bool {
+		return update_GetAddresses_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAddresses_ResponseParams_Versions) {
+		if update_GetAddresses_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAddresses_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			len0, err := decoder.StartArray(64)
+			if err != nil {
+				return err
+			}
+			s.outAddresses = make([]string, len0)
+			for i0 := uint32(0); i0 < len0; i0++ {
+				pointer1, err := decoder.ReadPointer()
+				if err != nil {
+					return err
+				}
+				if pointer1 == 0 {
+					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+				} else {
+					value1, err := decoder.ReadString()
+					if err != nil {
+						return err
+					}
+					s.outAddresses[i0] = value1
+				}
+			}
+			if err := decoder.Finish(); err != nil {
+				return err
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Update_Proxy) GetAddresses() (outAddresses []string, err error) {
+	payload := &update_GetAddresses_Params{}
+	header := bindings.MessageHeader{
+		Type:      update_GetAddresses_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, update_GetAddresses_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response update_GetAddresses_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	outAddresses = response.outAddresses
+	return
+}
+
+type update_GetAttribute_Params struct {
+	inName string
+}
+
+func (s *update_GetAttribute_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	if err := encoder.WriteString(s.inName); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAttribute_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetAttribute_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAttribute_Params_Versions), func(i int) bool {
+		return update_GetAttribute_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAttribute_Params_Versions) {
+		if update_GetAttribute_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAttribute_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			value0, err := decoder.ReadString()
+			if err != nil {
+				return err
+			}
+			s.inName = value0
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type update_GetAttribute_ResponseParams struct {
+	outAttribute string
+}
+
+func (s *update_GetAttribute_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	if err := encoder.WriteString(s.outAttribute); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAttribute_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetAttribute_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAttribute_ResponseParams_Versions), func(i int) bool {
+		return update_GetAttribute_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAttribute_ResponseParams_Versions) {
+		if update_GetAttribute_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAttribute_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			value0, err := decoder.ReadString()
+			if err != nil {
+				return err
+			}
+			s.outAttribute = value0
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Update_Proxy) GetAttribute(inName string) (outAttribute string, err error) {
+	payload := &update_GetAttribute_Params{
+		inName,
+	}
+	header := bindings.MessageHeader{
+		Type:      update_GetAttribute_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, update_GetAttribute_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response update_GetAttribute_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	outAttribute = response.outAttribute
+	return
+}
+
+type update_GetAttachment_Params struct {
+	inName string
+}
+
+func (s *update_GetAttachment_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	if err := encoder.WriteString(s.inName); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAttachment_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetAttachment_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAttachment_Params_Versions), func(i int) bool {
+		return update_GetAttachment_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAttachment_Params_Versions) {
+		if update_GetAttachment_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAttachment_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			value0, err := decoder.ReadString()
+			if err != nil {
+				return err
+			}
+			s.inName = value0
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type update_GetAttachment_ResponseParams struct {
+	outData system.ConsumerHandle
+}
+
+func (s *update_GetAttachment_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WriteHandle(s.outData); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAttachment_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetAttachment_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAttachment_ResponseParams_Versions), func(i int) bool {
+		return update_GetAttachment_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAttachment_ResponseParams_Versions) {
+		if update_GetAttachment_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAttachment_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		handle0, err := decoder.ReadConsumerHandle()
+		if err != nil {
+			return err
+		}
+		if handle0.IsValid() {
+			s.outData = handle0
+		} else {
+			return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Update_Proxy) GetAttachment(inName string) (outData system.ConsumerHandle, err error) {
+	payload := &update_GetAttachment_Params{
+		inName,
+	}
+	header := bindings.MessageHeader{
+		Type:      update_GetAttachment_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, update_GetAttachment_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response update_GetAttachment_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	outData = response.outData
+	return
+}
+
+type update_GetAdvertisement_Params struct {
+}
+
+func (s *update_GetAdvertisement_Params) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(0, 0)
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAdvertisement_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{8, 0},
+}
+
+func (s *update_GetAdvertisement_Params) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAdvertisement_Params_Versions), func(i int) bool {
+		return update_GetAdvertisement_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAdvertisement_Params_Versions) {
+		if update_GetAdvertisement_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAdvertisement_Params_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type update_GetAdvertisement_ResponseParams struct {
+	outAd Advertisement
+}
+
+func (s *update_GetAdvertisement_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(8, 0)
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	if err := s.outAd.Encode(encoder); err != nil {
+		return err
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+var update_GetAdvertisement_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{16, 0},
+}
+
+func (s *update_GetAdvertisement_ResponseParams) Decode(decoder *bindings.Decoder) error {
+	header, err := decoder.StartStruct()
+	if err != nil {
+		return err
+	}
+	index := sort.Search(len(update_GetAdvertisement_ResponseParams_Versions), func(i int) bool {
+		return update_GetAdvertisement_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	})
+	if index < len(update_GetAdvertisement_ResponseParams_Versions) {
+		if update_GetAdvertisement_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+			index--
+		}
+		expectedSize := update_GetAdvertisement_ResponseParams_Versions[index].Size
+		if expectedSize != header.Size {
+			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
+				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			if err := s.outAd.Decode(decoder); err != nil {
+				return err
+			}
+		}
+	}
+	if err := decoder.Finish(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p *Update_Proxy) GetAdvertisement() (outAd Advertisement, err error) {
+	payload := &update_GetAdvertisement_Params{}
+	header := bindings.MessageHeader{
+		Type:      update_GetAdvertisement_Name,
+		Flags:     bindings.MessageExpectsResponseFlag,
+		RequestId: p.ids.Count(),
+	}
+	var message *bindings.Message
+	if message, err = bindings.EncodeMessage(header, payload); err != nil {
+		err = fmt.Errorf("can't encode request: %v", err.Error())
+		p.Close_Proxy()
+		return
+	}
+	readResult := <-p.router.AcceptWithResponse(message)
+	if err = readResult.Error; err != nil {
+		p.Close_Proxy()
+		return
+	}
+	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
+		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
+		}
+		return
+	}
+	if got, want := readResult.Message.Header.Type, update_GetAdvertisement_Name; got != want {
+		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
+		}
+		return
+	}
+	var response update_GetAdvertisement_ResponseParams
+	if err = readResult.Message.DecodePayload(&response); err != nil {
+		p.Close_Proxy()
+		return
+	}
+	outAd = response.outAd
+	return
+}
+
+type update_Stub struct {
+	connector *bindings.Connector
+	impl      Update
+}
+
+func NewUpdateStub(r Update_Request, impl Update, waiter bindings.AsyncWaiter) *bindings.Stub {
+	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
+	return bindings.NewStub(connector, &update_Stub{connector, impl})
+}
+
+func (f *Update_Request) ServiceDescription() service_describer.ServiceDescription {
+	return &Update_ServiceDescription{}
+}
+
+type Update_ServiceDescription struct{}
+
+func (sd *Update_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
+	err = fmt.Errorf("GetTopLevelInterface not implemented")
+	return
+}
+
+func (sd *Update_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
+	err = fmt.Errorf("GetTypeDefinition not implemented")
+	return
+}
+
+func (sd *Update_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
+	err = fmt.Errorf("GetAllTypeDefinitions not implemented")
+	return
+}
+
+var _ service_describer.ServiceDescription = (*Update_ServiceDescription)(nil)
+
+func (s *update_Stub) Accept(message *bindings.Message) (err error) {
+	switch message.Header.Type {
+	case update_IsLost_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request update_IsLost_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response update_IsLost_ResponseParams
+		response.outLost, err = s.impl.IsLost()
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      update_IsLost_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case update_GetId_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request update_GetId_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response update_GetId_ResponseParams
+		response.outId, err = s.impl.GetId()
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      update_GetId_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case update_GetInterfaceName_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request update_GetInterfaceName_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response update_GetInterfaceName_ResponseParams
+		response.outInterfaceName, err = s.impl.GetInterfaceName()
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      update_GetInterfaceName_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case update_GetAddresses_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request update_GetAddresses_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response update_GetAddresses_ResponseParams
+		response.outAddresses, err = s.impl.GetAddresses()
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      update_GetAddresses_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case update_GetAttribute_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request update_GetAttribute_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response update_GetAttribute_ResponseParams
+		response.outAttribute, err = s.impl.GetAttribute(request.inName)
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      update_GetAttribute_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case update_GetAttachment_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request update_GetAttachment_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response update_GetAttachment_ResponseParams
+		response.outData, err = s.impl.GetAttachment(request.inName)
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      update_GetAttachment_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case update_GetAdvertisement_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request update_GetAdvertisement_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response update_GetAdvertisement_ResponseParams
+		response.outAd, err = s.impl.GetAdvertisement()
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      update_GetAdvertisement_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	default:
+		return &bindings.ValidationError{
+			bindings.MessageHeaderUnknownMethod,
+			fmt.Sprintf("unknown method %v", message.Header.Type),
+		}
+	}
+	return
+}
+
+type Advertisement struct {
+	Id            *[16]uint8
+	InterfaceName string
+	Addresses     []string
+	Attributes    *map[string]string
+	Attachments   *map[string][]uint8
+}
+
+func (s *Advertisement) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(40, 0)
+	if s.Id == nil {
 		encoder.WriteNullPointer()
 	} else {
 		if err := encoder.WritePointer(); err != nil {
 			return err
 		}
-		if err := encoder.WriteString((*s.InstanceName)); err != nil {
+		encoder.StartArray(uint32(len((*s.Id))), 8)
+		for _, elem0 := range *s.Id {
+			if err := encoder.WriteUint8(elem0); err != nil {
+				return err
+			}
+		}
+		if err := encoder.Finish(); err != nil {
 			return err
 		}
 	}
@@ -1246,7 +2472,22 @@
 	if err := encoder.WriteString(s.InterfaceName); err != nil {
 		return err
 	}
-	if s.Attrs == nil {
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	encoder.StartArray(uint32(len(s.Addresses)), 64)
+	for _, elem0 := range s.Addresses {
+		if err := encoder.WritePointer(); err != nil {
+			return err
+		}
+		if err := encoder.WriteString(elem0); err != nil {
+			return err
+		}
+	}
+	if err := encoder.Finish(); err != nil {
+		return err
+	}
+	if s.Attributes == nil {
 		encoder.WriteNullPointer()
 	} else {
 		if err := encoder.WritePointer(); err != nil {
@@ -1256,7 +2497,7 @@
 		{
 			var keys0 []string
 			var values0 []string
-			for key0, value0 := range *s.Attrs {
+			for key0, value0 := range *s.Attributes {
 				keys0 = append(keys0, key0)
 				values0 = append(values0, value0)
 			}
@@ -1295,21 +2536,6 @@
 			return err
 		}
 	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.Addrs)), 64)
-	for _, elem0 := range s.Addrs {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := encoder.WriteString(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
 	if s.Attachments == nil {
 		encoder.WriteNullPointer()
 	} else {
@@ -1371,23 +2597,23 @@
 	return nil
 }
 
-var service_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{56, 0},
+var advertisement_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{48, 0},
 }
 
-func (s *Service) Decode(decoder *bindings.Decoder) error {
+func (s *Advertisement) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(service_Versions), func(i int) bool {
-		return service_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(advertisement_Versions), func(i int) bool {
+		return advertisement_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(service_Versions) {
-		if service_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(advertisement_Versions) {
+		if advertisement_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := service_Versions[index].Size
+		expectedSize := advertisement_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -1400,30 +2626,28 @@
 			return err
 		}
 		if pointer0 == 0 {
-			s.InstanceId = nil
+			s.Id = nil
 		} else {
-			s.InstanceId = new(string)
-			value0, err := decoder.ReadString()
+			s.Id = new([16]uint8)
+			len0, err := decoder.StartArray(8)
 			if err != nil {
 				return err
 			}
-			(*s.InstanceId) = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			s.InstanceName = nil
-		} else {
-			s.InstanceName = new(string)
-			value0, err := decoder.ReadString()
-			if err != nil {
+			if len0 != 16 {
+				return &bindings.ValidationError{bindings.UnexpectedArrayHeader,
+					fmt.Sprintf("invalid array length: expected %d, got %d", 16, len0),
+				}
+			}
+			for i0 := uint32(0); i0 < len0; i0++ {
+				value1, err := decoder.ReadUint8()
+				if err != nil {
+					return err
+				}
+				(*s.Id)[i0] = value1
+			}
+			if err := decoder.Finish(); err != nil {
 				return err
 			}
-			(*s.InstanceName) = value0
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
@@ -1447,9 +2671,42 @@
 			return err
 		}
 		if pointer0 == 0 {
-			s.Attrs = nil
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
 		} else {
-			s.Attrs = new(map[string]string)
+			len0, err := decoder.StartArray(64)
+			if err != nil {
+				return err
+			}
+			s.Addresses = make([]string, len0)
+			for i0 := uint32(0); i0 < len0; i0++ {
+				pointer1, err := decoder.ReadPointer()
+				if err != nil {
+					return err
+				}
+				if pointer1 == 0 {
+					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+				} else {
+					value1, err := decoder.ReadString()
+					if err != nil {
+						return err
+					}
+					s.Addresses[i0] = value1
+				}
+			}
+			if err := decoder.Finish(); err != nil {
+				return err
+			}
+		}
+	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			s.Attributes = nil
+		} else {
+			s.Attributes = new(map[string]string)
 			if err := decoder.StartMap(); err != nil {
 				return err
 			}
@@ -1534,40 +2791,7 @@
 			for i0 := 0; i0 < len0; i0++ {
 				map0[keys0[i0]] = values0[i0]
 			}
-			(*s.Attrs) = map0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(64)
-			if err != nil {
-				return err
-			}
-			s.Addrs = make([]string, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				pointer1, err := decoder.ReadPointer()
-				if err != nil {
-					return err
-				}
-				if pointer1 == 0 {
-					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-				} else {
-					value1, err := decoder.ReadString()
-					if err != nil {
-						return err
-					}
-					s.Addrs[i0] = value1
-				}
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
+			(*s.Attributes) = map0
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
@@ -1682,81 +2906,10 @@
 	return nil
 }
 
-type ScanUpdate struct {
-	Service    Service
-	UpdateType UpdateType
-}
-
-func (s *ScanUpdate) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.Service.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WriteInt32(int32(s.UpdateType)); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var scanUpdate_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *ScanUpdate) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(scanUpdate_Versions), func(i int) bool {
-		return scanUpdate_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(scanUpdate_Versions) {
-		if scanUpdate_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := scanUpdate_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.Service.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadInt32()
-		if err != nil {
-			return err
-		}
-		s.UpdateType = UpdateType(value0)
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
 type Error struct {
-	Id     string
-	Action int32
-	Msg    string
+	Id         string
+	ActionCode uint32
+	Msg        string
 }
 
 func (s *Error) Encode(encoder *bindings.Encoder) error {
@@ -1767,7 +2920,7 @@
 	if err := encoder.WriteString(s.Id); err != nil {
 		return err
 	}
-	if err := encoder.WriteInt32(s.Action); err != nil {
+	if err := encoder.WriteUint32(s.ActionCode); err != nil {
 		return err
 	}
 	if err := encoder.WritePointer(); err != nil {
@@ -1821,11 +2974,11 @@
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadInt32()
+		value0, err := decoder.ReadUint32()
 		if err != nil {
 			return err
 		}
-		s.Action = value0
+		s.ActionCode = value0
 	}
 	if header.ElementsOrVersion >= 0 {
 		pointer0, err := decoder.ReadPointer()
diff --git a/go/src/vanadium/discovery/internal/discovery.go b/go/src/vanadium/discovery/internal/discovery.go
index 949995a..a068b3b 100644
--- a/go/src/vanadium/discovery/internal/discovery.go
+++ b/go/src/vanadium/discovery/internal/discovery.go
@@ -14,220 +14,183 @@
 	"v.io/v23"
 	"v.io/v23/context"
 	"v.io/v23/discovery"
-	"v.io/v23/security"
-	"v.io/v23/verror"
 )
 
-const pkgPath = "mojo/vanadium/discovery/vanadium/discovery"
+// TODO(jhahn): Mojom 'const' is ignored in mojom.go. Remove this once it is fixed.
+const AdIdLen = 16
 
-var (
-	errInvalidInstanceId = verror.Register(pkgPath+".errInvalidInstanceId", verror.NoRetry, "{1:}{2:} instance id not valid")
-	errInvalidScanId     = verror.Register(pkgPath+".errInvalidScanId", verror.NoRetry, "{1:}{2:} scan id not valid")
-)
+// closer implements the mojom.Closer.
+type closer struct {
+	cancel func()
+}
 
-type DiscoveryCloser interface {
+func (c *closer) Close() error {
+	c.cancel()
+	return nil
+}
+
+type discoveryCloser interface {
 	mojom.Discovery
 
 	// Close closes all active tasks.
 	Close()
 }
 
-// mdiscovery is basically a thin wrapper around the Vanadium discovery API.
+// mdiscovery is a thin wrapper around the Vanadium discovery.
 type mdiscovery struct {
 	ctx *context.T
 	d   discovery.T
 
-	mu          sync.Mutex
-	activeAdvs  map[string]func() // GUARDED_BY(mu)
-	activeScans map[uint32]func() // GUARDED_BY(mu)
-	nextScanId  uint32            // GUARDED_BY(mu)
+	mu    sync.Mutex
+	stubs map[*bindings.Stub]struct{} // GUARDED_BY(mu)
 }
 
-func v2mError(err error) *mojom.Error {
-	return &mojom.Error{
-		Id:     string(verror.ErrorID(err)),
-		Action: int32(verror.Action(err)),
-		Msg:    err.Error(),
+func (d *mdiscovery) Advertise(ad mojom.Advertisement, visibility *[]string) (*[AdIdLen]uint8, *mojom.Closer_Pointer, *mojom.Error, error) {
+	// There is no way to mock _Pointer or _Request types. So we put Advertise()
+	// logic into a separate function doAdvertise() for unit testing.
+	closer, err := d.doAdvertise(&ad, visibility)
+	if err != nil {
+		return nil, nil, v2mError(err), nil
 	}
+
+	req, ptr := mojom.CreateMessagePipeForCloser()
+	stub := mojom.NewCloserStub(req, closer, bindings.GetAsyncWaiter())
+	d.serveStub(stub, closer.cancel)
+	return ad.Id, &ptr, nil, nil
 }
 
-func v2mService(s discovery.Service) mojom.Service {
-	mService := mojom.Service{
-		InterfaceName: s.InterfaceName,
-		Addrs:         s.Addrs,
-	}
-	if len(s.InstanceId) > 0 {
-		mService.InstanceId = &s.InstanceId
-	}
-	if len(s.InstanceName) > 0 {
-		mService.InstanceName = &s.InstanceName
-	}
-	if len(s.Attrs) > 0 {
-		attrs := map[string]string(s.Attrs)
-		mService.Attrs = &attrs
-	}
-	if len(s.Attachments) > 0 {
-		attachments := map[string][]byte(s.Attachments)
-		mService.Attachments = &attachments
-	}
-	return mService
-}
-
-func (d *mdiscovery) StartAdvertising(service mojom.Service, visibility *[]string) (string, *mojom.Error, error) {
-	vService := discovery.Service{
-		InterfaceName: service.InterfaceName,
-		Addrs:         service.Addrs,
-	}
-	if service.InstanceId != nil {
-		vService.InstanceId = *service.InstanceId
-	}
-	if service.InstanceName != nil {
-		vService.InstanceName = *service.InstanceName
-	}
-	if service.Attrs != nil {
-		vService.Attrs = *service.Attrs
-	}
-	if service.Attachments != nil {
-		vService.Attachments = *service.Attachments
-	}
-	var vVisibility []security.BlessingPattern
-	if visibility != nil {
-		vVisibility := make([]security.BlessingPattern, len(*visibility))
-		for i, p := range *visibility {
-			vVisibility[i] = security.BlessingPattern(p)
-		}
-	}
+func (d *mdiscovery) doAdvertise(ad *mojom.Advertisement, visibility *[]string) (*closer, error) {
+	vAd := m2vAd(ad)
+	vVisibility := m2vVisibility(visibility)
 
 	ctx, cancel := context.WithCancel(d.ctx)
-	done, err := d.d.Advertise(ctx, &vService, vVisibility)
+	done, err := d.d.Advertise(ctx, &vAd, vVisibility)
 	if err != nil {
 		cancel()
-		return "", v2mError(err), nil
+		return nil, err
 	}
+	if ad.Id == nil {
+		ad.Id = new([AdIdLen]uint8)
+	}
+	*ad.Id = vAd.Id
 	stop := func() {
 		cancel()
 		<-done
 	}
-
-	d.mu.Lock()
-	d.activeAdvs[vService.InstanceId] = stop
-	d.mu.Unlock()
-	return vService.InstanceId, nil, nil
-}
-
-func (d *mdiscovery) StopAdvertising(instanceId string) (*mojom.Error, error) {
-	d.mu.Lock()
-	stop := d.activeAdvs[instanceId]
-	delete(d.activeAdvs, instanceId)
-	d.mu.Unlock()
-	if stop == nil {
-		return v2mError(verror.New(errInvalidInstanceId, d.ctx)), nil
-	}
-	stop()
-	return nil, nil
-}
-
-func (d *mdiscovery) StartScan(query string, handlerPtr mojom.ScanHandler_Pointer) (uint32, *mojom.Error, error) {
-	// There is no way to mock _Pointer or _Request types. So we put StartScan()
-	// logic into a separate function startScan() for unit testing.
-	proxy := mojom.NewScanHandlerProxy(handlerPtr, bindings.GetAsyncWaiter())
-	return d.startScan(query, proxy)
+	return &closer{stop}, nil
 }
 
 type scanHandlerProxy interface {
-	mojom.ScanHandler
+	passUpdate(update mojom.Update) error
 	Close_Proxy()
 }
 
-func (d *mdiscovery) startScan(query string, proxy scanHandlerProxy) (uint32, *mojom.Error, error) {
+type scanHandlerProxyImpl struct {
+	*mojom.ScanHandler_Proxy
+
+	d *mdiscovery
+}
+
+func (p *scanHandlerProxyImpl) passUpdate(update mojom.Update) error {
+	req, ptr := mojom.CreateMessagePipeForUpdate()
+	stub := mojom.NewUpdateStub(req, update, bindings.GetAsyncWaiter())
+	p.d.serveStub(stub, nil)
+	return p.OnUpdate(ptr)
+}
+
+func (d *mdiscovery) Scan(query string, handlerPtr mojom.ScanHandler_Pointer) (*mojom.Closer_Pointer, *mojom.Error, error) {
+	// There is no way to mock _Pointer or _Request types. So we put Scan()
+	// logic into a separate function doScan() for unit testing.
+	proxy := mojom.NewScanHandlerProxy(handlerPtr, bindings.GetAsyncWaiter())
+	closer, err := d.doScan(query, &scanHandlerProxyImpl{proxy, d})
+	if err != nil {
+		return nil, v2mError(err), nil
+	}
+
+	req, ptr := mojom.CreateMessagePipeForCloser()
+	stub := mojom.NewCloserStub(req, closer, bindings.GetAsyncWaiter())
+	d.serveStub(stub, closer.cancel)
+	return &ptr, nil, nil
+}
+
+func (d *mdiscovery) doScan(query string, proxy scanHandlerProxy) (*closer, error) {
 	ctx, cancel := context.WithCancel(d.ctx)
 	scanCh, err := d.d.Scan(ctx, query)
 	if err != nil {
 		cancel()
 		proxy.Close_Proxy()
-		return 0, v2mError(err), nil
+		return nil, err
 	}
 
-	d.mu.Lock()
-	scanId := d.nextScanId
-	d.activeScans[scanId] = cancel
-	d.nextScanId++
-	d.mu.Unlock()
-
 	go func() {
 		defer proxy.Close_Proxy()
 
 		for update := range scanCh {
-			var mupdate mojom.ScanUpdate
-			switch u := update.(type) {
-			case discovery.UpdateFound:
-				mupdate = mojom.ScanUpdate{
-					Service:    v2mService(u.Value.Service),
-					UpdateType: mojom.UpdateType_Found,
-				}
-			case discovery.UpdateLost:
-				mupdate = mojom.ScanUpdate{
-					Service:    v2mService(u.Value.Service),
-					UpdateType: mojom.UpdateType_Lost,
-				}
-			}
-			if err := proxy.Update(mupdate); err != nil {
+			mUpdate := newMojoUpdate(ctx, update)
+			if err := proxy.passUpdate(mUpdate); err != nil {
 				return
 			}
 		}
 	}()
-
-	return scanId, nil, nil
+	return &closer{cancel}, nil
 }
 
-func (d *mdiscovery) StopScan(scanId uint32) (*mojom.Error, error) {
+func (d *mdiscovery) serveStub(stub *bindings.Stub, cleanup func()) {
 	d.mu.Lock()
-	stop := d.activeScans[scanId]
-	delete(d.activeScans, scanId)
+	d.stubs[stub] = struct{}{}
 	d.mu.Unlock()
-	if stop == nil {
-		return v2mError(verror.New(errInvalidScanId, d.ctx)), nil
-	}
-	stop()
-	return nil, nil
+
+	go func() {
+		for {
+			if err := stub.ServeRequest(); err != nil {
+				connErr, ok := err.(*bindings.ConnectionError)
+				if !ok || !connErr.Closed() {
+					d.ctx.Error(err)
+				}
+				break
+			}
+		}
+
+		d.mu.Lock()
+		delete(d.stubs, stub)
+		d.mu.Unlock()
+
+		if cleanup != nil {
+			cleanup()
+		}
+	}()
 }
 
 func (d *mdiscovery) Close() {
 	d.mu.Lock()
 	defer d.mu.Unlock()
 
-	for _, stop := range d.activeAdvs {
-		stop()
-	}
-	for _, stop := range d.activeScans {
-		stop()
+	for stub := range d.stubs {
+		stub.Close()
 	}
 }
 
 // ediscovery always returns the given error.
 type ediscovery struct{ err error }
 
-func (d *ediscovery) StartAdvertising(mojom.Service, *[]string) (string, *mojom.Error, error) {
-	return "", v2mError(d.err), nil
+func (d *ediscovery) Advertise(mojom.Advertisement, *[]string) (*[AdIdLen]uint8, *mojom.Closer_Pointer, *mojom.Error, error) {
+	return nil, nil, v2mError(d.err), nil
 }
-func (d *ediscovery) StopAdvertising(string) (*mojom.Error, error) { return v2mError(d.err), nil }
-func (d *ediscovery) StartScan(string, mojom.ScanHandler_Pointer) (uint32, *mojom.Error, error) {
-	return 0, v2mError(d.err), nil
+func (d *ediscovery) Scan(string, mojom.ScanHandler_Pointer) (*mojom.Closer_Pointer, *mojom.Error, error) {
+	return nil, v2mError(d.err), nil
 }
-func (d *ediscovery) StopScan(uint32) (*mojom.Error, error) { return v2mError(d.err), nil }
-func (d *ediscovery) Close()                                {}
+func (d *ediscovery) Close() {}
 
 // NewDiscovery returns a new Vanadium discovery instance.
-func NewDiscovery(ctx *context.T) DiscoveryCloser {
+func NewDiscovery(ctx *context.T) discoveryCloser {
 	d, err := v23.NewDiscovery(ctx)
 	if err != nil {
 		return &ediscovery{err}
 	}
 
 	return &mdiscovery{
-		ctx:         ctx,
-		d:           d,
-		activeAdvs:  make(map[string]func()),
-		activeScans: make(map[uint32]func()),
+		ctx:   ctx,
+		d:     d,
+		stubs: make(map[*bindings.Stub]struct{}),
 	}
 }
diff --git a/go/src/vanadium/discovery/internal/discovery_test.go b/go/src/vanadium/discovery/internal/discovery_test.go
index a34cc8c..93e809b 100644
--- a/go/src/vanadium/discovery/internal/discovery_test.go
+++ b/go/src/vanadium/discovery/internal/discovery_test.go
@@ -5,17 +5,13 @@
 package internal
 
 import (
-	"errors"
 	"fmt"
 	"reflect"
-	"runtime"
 	"testing"
 	"time"
 
 	mojom "mojom/vanadium/discovery"
 
-	"v.io/v23/discovery"
-
 	idiscovery "v.io/x/ref/lib/discovery"
 	dfactory "v.io/x/ref/lib/discovery/factory"
 	"v.io/x/ref/lib/discovery/plugins/mock"
@@ -30,36 +26,33 @@
 	df, _ := idiscovery.NewFactory(ctx, mock.New())
 	dfactory.InjectFactory(df)
 
-	services := []discovery.Service{
+	ads := []mojom.Advertisement{
 		{
-			InstanceId:    "123",
+			Id:            &[AdIdLen]uint8{1, 2, 3},
 			InterfaceName: "v.io/v23/a",
-			Attrs:         discovery.Attributes{"a1": "v1"},
-			Addrs:         []string{"/h1:123/x"},
+			Addresses:     []string{"/h1:123/x"},
+			Attributes:    &map[string]string{"a1": "v1"},
 		},
 		{
 			InterfaceName: "v.io/v23/b",
-			Attrs:         discovery.Attributes{"b1": "v1"},
-			Addrs:         []string{"/h1:123/y"},
+			Addresses:     []string{"/h1:123/y"},
+			Attributes:    &map[string]string{"b1": "v1"},
 		},
 	}
 
 	d1 := NewDiscovery(ctx)
+	defer d1.Close()
 
-	for i, service := range services {
-		instanceId, merr, err := d1.StartAdvertising(mkMojomService(service), nil)
-		if merr != nil || err != nil {
-			t.Fatalf("failed to advertise service: %v, %v", merr, err)
+	var adClosers []mojom.Closer
+	for i, _ := range ads {
+		closer, err := d1.(*mdiscovery).doAdvertise(&ads[i], nil)
+		if err != nil {
+			t.Fatalf("ad[%d]: failed to advertise: %v", i, err)
 		}
-		if len(instanceId) == 0 {
-			t.Errorf("service[%d]: got empty instance id", i)
+		if ads[i].Id == nil {
+			t.Errorf("ad[%d]: got nil id", i)
 		}
-
-		if len(service.InstanceId) == 0 {
-			services[i].InstanceId = instanceId
-		} else if instanceId != service.InstanceId {
-			t.Errorf("service[%d]: got instance id %v, but wanted %v", i, instanceId, service.InstanceId)
-		}
+		adClosers = append(adClosers, closer)
 	}
 
 	// Make sure none of advertisements are discoverable by the same discovery instance.
@@ -69,99 +62,76 @@
 
 	// Create a new discovery instance. All advertisements should be discovered with that.
 	d2 := NewDiscovery(ctx)
+	defer d2.Close()
 
-	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/a"`, services[0]); err != nil {
+	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/a"`, ads[0]); err != nil {
 		t.Error(err)
 	}
-	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/b"`, services[1]); err != nil {
+
+	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/b"`, ads[1]); err != nil {
 		t.Error(err)
 	}
-	if err := scanAndMatch(d2, "", services...); err != nil {
+	if err := scanAndMatch(d2, ``, ads...); err != nil {
 		t.Error(err)
 	}
 
 	// Open a new scan channel and consume expected advertisements first.
-	scanCh, scanStop, err := startScan(d2, `v.InterfaceName="v.io/v23/a"`)
+	scanCh, scanCloser, err := scan(d2, `v.InterfaceName="v.io/v23/a"`)
 	if err != nil {
 		t.Fatal(err)
 	}
-	defer scanStop()
+	defer scanCloser.Close()
 	update := <-scanCh
-	if !matchFound([]mojom.ScanUpdate{update}, services[0]) {
+	if !matchFound([]mojom.Update{update}, ads[0]) {
 		t.Errorf("unexpected scan: %v", update)
 	}
 
 	// Make sure scan returns the lost advertisement when advertising is stopped.
-	d1.StopAdvertising(services[0].InstanceId)
+	adClosers[0].Close()
 
 	update = <-scanCh
-	if !matchLost([]mojom.ScanUpdate{update}, services[0]) {
+	if !matchLost([]mojom.Update{update}, ads[0]) {
 		t.Errorf("unexpected scan: %v", update)
 	}
 
 	// Also it shouldn't affect the other.
-	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/b"`, services[1]); err != nil {
+	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/b"`, ads[1]); err != nil {
 		t.Error(err)
 	}
 
-	// Stop advertising the remaining one; Shouldn't discover any service.
-	d1.StopAdvertising(services[1].InstanceId)
+	// Stop advertising the remaining one; Shouldn't discover any advertisements.
+	adClosers[1].Close()
 	if err := scanAndMatch(d2, ""); err != nil {
 		t.Error(err)
 	}
 }
 
 type mockScanHandler struct {
-	ch chan mojom.ScanUpdate
+	ch chan mojom.Update
 }
 
-func (m *mockScanHandler) Update(u mojom.ScanUpdate) error {
+func (m *mockScanHandler) Close_Proxy() { close(m.ch) }
+func (m *mockScanHandler) passUpdate(u mojom.Update) error {
 	m.ch <- u
 	return nil
 }
-func (m *mockScanHandler) Close_Proxy() { close(m.ch) }
 
-func startScan(d mojom.Discovery, query string) (<-chan mojom.ScanUpdate, func(), error) {
-	ch := make(chan mojom.ScanUpdate)
-	scanId, merr, err := d.(*mdiscovery).startScan(query, &mockScanHandler{ch})
-	if merr != nil {
-		return nil, nil, errors.New(merr.Msg)
-	}
+func scan(d mojom.Discovery, query string) (<-chan mojom.Update, mojom.Closer, error) {
+	ch := make(chan mojom.Update)
+	closer, err := d.(*mdiscovery).doScan(query, &mockScanHandler{ch})
 	if err != nil {
 		return nil, nil, err
 	}
-
-	stop := func() { d.StopScan(scanId) }
-	return ch, stop, nil
+	return ch, closer, nil
 }
 
-func scan(d mojom.Discovery, query string) ([]mojom.ScanUpdate, error) {
-	ch, stop, err := startScan(d, query)
-	if err != nil {
-		return nil, err
-	}
-	defer stop()
+func scanAndMatch(d mojom.Discovery, query string, wants ...mojom.Advertisement) error {
+	const timeout = 10 * time.Second
 
-	var updates []mojom.ScanUpdate
-	for {
-		select {
-		case update := <-ch:
-			updates = append(updates, update)
-		case <-time.After(5 * time.Millisecond):
-			return updates, nil
-		}
-	}
-}
-
-func scanAndMatch(d mojom.Discovery, query string, wants ...discovery.Service) error {
-	const timeout = 3 * time.Second
-
-	var updates []mojom.ScanUpdate
+	var updates []mojom.Update
 	for now := time.Now(); time.Since(now) < timeout; {
-		runtime.Gosched()
-
 		var err error
-		updates, err = scan(d, query)
+		updates, err = doScan(d, query, len(wants))
 		if err != nil {
 			return err
 		}
@@ -172,47 +142,58 @@
 	return fmt.Errorf("Match failed; got %v, but wanted %v", updates, wants)
 }
 
-func match(updates []mojom.ScanUpdate, updateType mojom.UpdateType, wants ...discovery.Service) bool {
-	for _, want := range wants {
-		matched := false
-		for i, update := range updates {
-			if update.UpdateType == updateType && reflect.DeepEqual(update.Service, mkMojomService(want)) {
-				updates = append(updates[:i], updates[i+1:]...)
-				matched = true
-				break
-			}
+func doScan(d mojom.Discovery, query string, expectedUpdates int) ([]mojom.Update, error) {
+	scanCh, closer, err := scan(d, query)
+	if err != nil {
+		return nil, err
+	}
+	defer closer.Close()
+
+	updates := make([]mojom.Update, 0, expectedUpdates)
+	for {
+		timeout := 5 * time.Millisecond
+		if len(updates) < expectedUpdates {
+			// Increase the timeout if we do not receive enough updates
+			// to avoid flakiness in unit tests.
+			timeout = 5 * time.Second
 		}
-		if !matched {
+
+		select {
+		case update := <-scanCh:
+			updates = append(updates, update)
+		case <-time.After(timeout):
+			return updates, nil
+		}
+	}
+}
+
+func matchFound(updates []mojom.Update, wants ...mojom.Advertisement) bool {
+	return match(updates, false, wants...)
+}
+
+func matchLost(updates []mojom.Update, wants ...mojom.Advertisement) bool {
+	return match(updates, true, wants...)
+}
+
+func match(updates []mojom.Update, lost bool, wants ...mojom.Advertisement) bool {
+	updateMap := make(map[[AdIdLen]uint8]mojom.Update)
+	for _, update := range updates {
+		id, _ := update.GetId()
+		updateMap[id] = update
+	}
+
+	for _, want := range wants {
+		update := updateMap[*want.Id]
+		if update == nil {
 			return false
 		}
+		if got, _ := update.IsLost(); got != lost {
+			return false
+		}
+		if got, _ := update.GetAdvertisement(); !reflect.DeepEqual(got, want) {
+			return false
+		}
+		delete(updateMap, *want.Id)
 	}
-	return len(updates) == 0
-}
-
-func matchFound(updates []mojom.ScanUpdate, wants ...discovery.Service) bool {
-	return match(updates, mojom.UpdateType_Found, wants...)
-}
-
-func matchLost(updates []mojom.ScanUpdate, wants ...discovery.Service) bool {
-	return match(updates, mojom.UpdateType_Lost, wants...)
-}
-
-func mkMojomService(service discovery.Service) mojom.Service {
-	mservice := mojom.Service{
-		InstanceId:    &service.InstanceId,
-		InterfaceName: service.InterfaceName,
-		Addrs:         service.Addrs,
-	}
-	if len(service.InstanceName) > 0 {
-		mservice.InstanceName = &service.InstanceName
-	}
-	if len(service.Attrs) > 0 {
-		attrs := map[string]string(service.Attrs)
-		mservice.Attrs = &attrs
-	}
-	if len(service.Attachments) > 0 {
-		attachments := map[string][]byte(service.Attachments)
-		mservice.Attachments = &attachments
-	}
-	return mservice
+	return len(updateMap) == 0
 }
diff --git a/go/src/vanadium/discovery/internal/update.go b/go/src/vanadium/discovery/internal/update.go
new file mode 100644
index 0000000..1732562
--- /dev/null
+++ b/go/src/vanadium/discovery/internal/update.go
@@ -0,0 +1,54 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+	"fmt"
+
+	"mojo/public/go/system"
+
+	mojom "mojom/vanadium/discovery"
+
+	"v.io/v23/context"
+	"v.io/v23/discovery"
+)
+
+type mupdate struct {
+	ctx *context.T
+	u   discovery.Update
+}
+
+func (u *mupdate) IsLost() (bool, error)                    { return u.u.IsLost(), nil }
+func (u *mupdate) GetId() ([AdIdLen]uint8, error)           { return u.u.Id(), nil }
+func (u *mupdate) GetInterfaceName() (string, error)        { return u.u.InterfaceName(), nil }
+func (u *mupdate) GetAddresses() ([]string, error)          { return u.u.Addresses(), nil }
+func (u *mupdate) GetAttribute(name string) (string, error) { return u.u.Attribute(name), nil }
+
+func (u *mupdate) GetAttachment(name string) (system.ConsumerHandle, error) {
+	r, producer, consumer := system.GetCore().CreateDataPipe(nil)
+	if r != system.MOJO_RESULT_OK {
+		return nil, fmt.Errorf("can't create data pipe: %v", r)
+	}
+	go func() {
+		defer producer.Close()
+
+		dataOrErr := <-u.u.Attachment(u.ctx, name)
+		if dataOrErr.Error != nil {
+			u.ctx.Error(dataOrErr.Error)
+		} else {
+			producer.WriteData([]byte(dataOrErr.Data), system.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)
+		}
+	}()
+	return consumer, nil
+}
+
+func (u *mupdate) GetAdvertisement() (mojom.Advertisement, error) {
+	ad := u.u.Advertisement()
+	return v2mAd(&ad), nil
+}
+
+func newMojoUpdate(ctx *context.T, update discovery.Update) mojom.Update {
+	return &mupdate{ctx, update}
+}
diff --git a/go/src/vanadium/discovery/internal/update_test.go b/go/src/vanadium/discovery/internal/update_test.go
new file mode 100644
index 0000000..05a2d8f
--- /dev/null
+++ b/go/src/vanadium/discovery/internal/update_test.go
@@ -0,0 +1,66 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+	"math/rand"
+	"reflect"
+	"testing"
+	"testing/quick"
+
+	"v.io/v23/context"
+	"v.io/v23/discovery"
+)
+
+type mockUpdate struct {
+	lost bool
+	ad   discovery.Advertisement
+}
+
+func (u *mockUpdate) IsLost() bool                                                        { return u.lost }
+func (u *mockUpdate) Id() discovery.AdId                                                  { return u.ad.Id }
+func (u *mockUpdate) InterfaceName() string                                               { return u.ad.InterfaceName }
+func (u *mockUpdate) Addresses() []string                                                 { return u.ad.Addresses }
+func (u *mockUpdate) Attribute(name string) string                                        { return u.ad.Attributes[name] }
+func (u *mockUpdate) Attachment(ctx *context.T, name string) <-chan discovery.DataOrError { return nil }
+func (u *mockUpdate) Advertisement() discovery.Advertisement                              { return u.ad }
+
+func TestUpdate(t *testing.T) {
+	rand := rand.New(rand.NewSource(0))
+	for i := 0; i < 10; i++ {
+		v, ok := quick.Value(reflect.TypeOf(discovery.Advertisement{}), rand)
+		if !ok {
+			t.Fatal("failed to populate value")
+		}
+
+		lost := rand.Int()%2 == 0
+		ad := v.Interface().(discovery.Advertisement)
+
+		mUpdate := newMojoUpdate(nil, &mockUpdate{lost, ad})
+
+		if got, _ := mUpdate.IsLost(); got != lost {
+			t.Errorf("IsLost: got %v, but want %v", got, lost)
+		}
+		if got, _ := mUpdate.GetId(); got != ad.Id {
+			t.Errorf("Id: got %v, but want %v", got, ad.Id)
+		}
+		if got, _ := mUpdate.GetInterfaceName(); got != ad.InterfaceName {
+			t.Errorf("InterfaceName: got %v, but want %v", got, ad.InterfaceName)
+		}
+		if got, _ := mUpdate.GetAddresses(); !reflect.DeepEqual(got, ad.Addresses) {
+			t.Errorf("Addresses: got %v, but want %v", got, ad.Addresses)
+		}
+		for k, v := range ad.Attributes {
+			if got, _ := mUpdate.GetAttribute(k); got != v {
+				t.Errorf("Attributes[%s]: got %v, but want %v", got, v)
+			}
+		}
+
+		mAd := v2mAd(&ad)
+		if got, _ := mUpdate.GetAdvertisement(); !reflect.DeepEqual(got, mAd) {
+			t.Errorf("Advertisement: got %v, but want %v", got, mAd)
+		}
+	}
+}
diff --git a/go/src/vanadium/discovery/internal/util.go b/go/src/vanadium/discovery/internal/util.go
new file mode 100644
index 0000000..785b102
--- /dev/null
+++ b/go/src/vanadium/discovery/internal/util.go
@@ -0,0 +1,69 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+	mojom "mojom/vanadium/discovery"
+
+	"v.io/v23/discovery"
+	"v.io/v23/security"
+	"v.io/v23/verror"
+)
+
+func v2mError(err error) *mojom.Error {
+	return &mojom.Error{
+		Id:         string(verror.ErrorID(err)),
+		ActionCode: uint32(verror.Action(err)),
+		Msg:        err.Error(),
+	}
+}
+
+func v2mAd(ad *discovery.Advertisement) mojom.Advertisement {
+	mAd := mojom.Advertisement{
+		InterfaceName: ad.InterfaceName,
+		Addresses:     ad.Addresses,
+	}
+	if ad.Id.IsValid() {
+		mAd.Id = new([AdIdLen]uint8)
+		*mAd.Id = ad.Id
+	}
+	if len(ad.Attributes) > 0 {
+		attributes := map[string]string(ad.Attributes)
+		mAd.Attributes = &attributes
+	}
+	if len(ad.Attachments) > 0 {
+		attachments := map[string][]byte(ad.Attachments)
+		mAd.Attachments = &attachments
+	}
+	return mAd
+}
+
+func m2vAd(ad *mojom.Advertisement) discovery.Advertisement {
+	vAd := discovery.Advertisement{
+		InterfaceName: ad.InterfaceName,
+		Addresses:     ad.Addresses,
+	}
+	if ad.Id != nil {
+		vAd.Id = *ad.Id
+	}
+	if ad.Attributes != nil {
+		vAd.Attributes = *ad.Attributes
+	}
+	if ad.Attachments != nil {
+		vAd.Attachments = *ad.Attachments
+	}
+	return vAd
+}
+
+func m2vVisibility(visibility *[]string) []security.BlessingPattern {
+	if visibility == nil {
+		return nil
+	}
+	vVisibility := make([]security.BlessingPattern, len(*visibility))
+	for i, p := range *visibility {
+		vVisibility[i] = security.BlessingPattern(p)
+	}
+	return vVisibility
+}
diff --git a/go/src/vanadium/discovery/internal/util_test.go b/go/src/vanadium/discovery/internal/util_test.go
new file mode 100644
index 0000000..72211b4
--- /dev/null
+++ b/go/src/vanadium/discovery/internal/util_test.go
@@ -0,0 +1,38 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+	"math/rand"
+	"reflect"
+	"testing"
+	"testing/quick"
+
+	"v.io/v23/discovery"
+)
+
+func TestConvAd(t *testing.T) {
+	rand := rand.New(rand.NewSource(0))
+	for i := 0; i < 10; i++ {
+		v, ok := quick.Value(reflect.TypeOf(discovery.Advertisement{}), rand)
+		if !ok {
+			t.Fatal("failed to populate value")
+		}
+		ad := v.Interface().(discovery.Advertisement)
+		// Make reflect.DeepEqual happy in comparing nil and empty.
+		if len(ad.Attributes) == 0 {
+			ad.Attributes = nil
+		}
+		if len(ad.Attachments) == 0 {
+			ad.Attachments = nil
+		}
+
+		mAd := v2mAd(&ad)
+		vAd := m2vAd(&mAd)
+		if !reflect.DeepEqual(vAd, ad) {
+			t.Errorf("Convert: got %v, but want %v", vAd, ad)
+		}
+	}
+}
diff --git a/java/generated-src/io/v/mojo/discovery/Service.java b/java/generated-src/io/v/mojo/discovery/Advertisement.java
similarity index 79%
rename from java/generated-src/io/v/mojo/discovery/Service.java
rename to java/generated-src/io/v/mojo/discovery/Advertisement.java
index 02b1510..e592867 100644
--- a/java/generated-src/io/v/mojo/discovery/Service.java
+++ b/java/generated-src/io/v/mojo/discovery/Advertisement.java
@@ -10,51 +10,59 @@
 
 package io.v.mojo.discovery;
 
-public final class Service extends org.chromium.mojo.bindings.Struct {
+public final class Advertisement extends org.chromium.mojo.bindings.Struct {
 
-    private static final int STRUCT_SIZE = 56;
-    private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(56, 0)};
+    private static final int STRUCT_SIZE = 48;
+    private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(48, 0)};
     private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
 
-    public String instanceId;
-    public String instanceName;
+    public static final int ID_LEN = (int) 16L;
+
+    public byte[] id;
     public String interfaceName;
-    public java.util.Map<String, String> attrs;
-    public String[] addrs;
+    public String[] addresses;
+    public java.util.Map<String, String> attributes;
     public java.util.Map<String, byte[]> attachments;
 
-    private Service(int version) {
+    private Advertisement(int version) {
         super(STRUCT_SIZE, version);
     }
 
-    public Service() {
+    public Advertisement() {
         this(0);
     }
 
-    public static Service deserialize(org.chromium.mojo.bindings.Message message) {
+    public static Advertisement deserialize(org.chromium.mojo.bindings.Message message) {
         return decode(new org.chromium.mojo.bindings.Decoder(message));
     }
 
     @SuppressWarnings("unchecked")
-    public static Service decode(org.chromium.mojo.bindings.Decoder decoder0) {
+    public static Advertisement decode(org.chromium.mojo.bindings.Decoder decoder0) {
         if (decoder0 == null) {
             return null;
         }
         org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-        Service result = new Service(mainDataHeader.elementsOrVersion);
+        Advertisement result = new Advertisement(mainDataHeader.elementsOrVersion);
         if (mainDataHeader.elementsOrVersion >= 0) {
-            result.instanceId = decoder0.readString(8, true);
+            result.id = decoder0.readBytes(8, org.chromium.mojo.bindings.BindingsHelper.ARRAY_NULLABLE, 16);
         }
         if (mainDataHeader.elementsOrVersion >= 0) {
-            result.instanceName = decoder0.readString(16, true);
+            result.interfaceName = decoder0.readString(16, false);
         }
         if (mainDataHeader.elementsOrVersion >= 0) {
-            result.interfaceName = decoder0.readString(24, false);
+            org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(24, false);
+            {
+                org.chromium.mojo.bindings.DataHeader si1 = decoder1.readDataHeaderForPointerArray(org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
+                result.addresses = new String[si1.elementsOrVersion];
+                for (int i1 = 0; i1 < si1.elementsOrVersion; ++i1) {
+                    result.addresses[i1] = decoder1.readString(org.chromium.mojo.bindings.DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i1, false);
+                }
+            }
         }
         if (mainDataHeader.elementsOrVersion >= 0) {
             org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(32, true);
             if (decoder1 == null) {
-                result.attrs = null;
+                result.attributes = null;
             } else {
                 decoder1.readDataHeaderForMap();
                 String[] keys0;
@@ -79,24 +87,14 @@
                         }
                     }
                 }
-                result.attrs = new java.util.HashMap<String, String>();
+                result.attributes = new java.util.HashMap<String, String>();
                 for (int index0 = 0; index0 < keys0.length; ++index0) {
-                    result.attrs.put(keys0[index0],  values0[index0]);
+                    result.attributes.put(keys0[index0],  values0[index0]);
                 }
             }
         }
         if (mainDataHeader.elementsOrVersion >= 0) {
-            org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(40, false);
-            {
-                org.chromium.mojo.bindings.DataHeader si1 = decoder1.readDataHeaderForPointerArray(org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
-                result.addrs = new String[si1.elementsOrVersion];
-                for (int i1 = 0; i1 < si1.elementsOrVersion; ++i1) {
-                    result.addrs[i1] = decoder1.readString(org.chromium.mojo.bindings.DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i1, false);
-                }
-            }
-        }
-        if (mainDataHeader.elementsOrVersion >= 0) {
-            org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(48, true);
+            org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(40, true);
             if (decoder1 == null) {
                 result.attachments = null;
             } else {
@@ -136,18 +134,25 @@
     @Override
     protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
         org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-        encoder0.encode(instanceId, 8, true);
-        encoder0.encode(instanceName, 16, true);
-        encoder0.encode(interfaceName, 24, false);
-        if (attrs == null) {
+        encoder0.encode(id, 8, org.chromium.mojo.bindings.BindingsHelper.ARRAY_NULLABLE, 16);
+        encoder0.encode(interfaceName, 16, false);
+        if (addresses == null) {
+            encoder0.encodeNullPointer(24, false);
+        } else {
+            org.chromium.mojo.bindings.Encoder encoder1 = encoder0.encodePointerArray(addresses.length, 24, org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
+            for (int i0 = 0; i0 < addresses.length; ++i0) {
+                encoder1.encode(addresses[i0], org.chromium.mojo.bindings.DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i0, false);
+            }
+        }
+        if (attributes == null) {
             encoder0.encodeNullPointer(32, true);
         } else {
             org.chromium.mojo.bindings.Encoder encoder1 = encoder0.encoderForMap(32);
-            int size0 = attrs.size();
+            int size0 = attributes.size();
             String[] keys0 = new String[size0];
             String[] values0 = new String[size0];
             int index0 = 0;
-            for (java.util.Map.Entry<String, String> entry0 : attrs.entrySet()) {
+            for (java.util.Map.Entry<String, String> entry0 : attributes.entrySet()) {
                 keys0[index0] = entry0.getKey();
                 values0[index0] = entry0.getValue();
                 ++index0;
@@ -165,18 +170,10 @@
                 }
             }
         }
-        if (addrs == null) {
-            encoder0.encodeNullPointer(40, false);
-        } else {
-            org.chromium.mojo.bindings.Encoder encoder1 = encoder0.encodePointerArray(addrs.length, 40, org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
-            for (int i0 = 0; i0 < addrs.length; ++i0) {
-                encoder1.encode(addrs[i0], org.chromium.mojo.bindings.DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i0, false);
-            }
-        }
         if (attachments == null) {
-            encoder0.encodeNullPointer(48, true);
+            encoder0.encodeNullPointer(40, true);
         } else {
-            org.chromium.mojo.bindings.Encoder encoder1 = encoder0.encoderForMap(48);
+            org.chromium.mojo.bindings.Encoder encoder1 = encoder0.encoderForMap(40);
             int size0 = attachments.size();
             String[] keys0 = new String[size0];
             byte[][] values0 = new byte[size0][];
@@ -212,16 +209,14 @@
             return false;
         if (getClass() != object.getClass())
             return false;
-        Service other = (Service) object;
-        if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.instanceId, other.instanceId))
-            return false;
-        if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.instanceName, other.instanceName))
+        Advertisement other = (Advertisement) object;
+        if (!java.util.Arrays.equals(this.id, other.id))
             return false;
         if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.interfaceName, other.interfaceName))
             return false;
-        if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.attrs, other.attrs))
+        if (!java.util.Arrays.deepEquals(this.addresses, other.addresses))
             return false;
-        if (!java.util.Arrays.deepEquals(this.addrs, other.addrs))
+        if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.attributes, other.attributes))
             return false;
         if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.attachments, other.attachments))
             return false;
@@ -235,11 +230,10 @@
     public int hashCode() {
         final int prime = 31;
         int result = prime + getClass().hashCode();
-        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(instanceId);
-        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(instanceName);
+        result = prime * result + java.util.Arrays.hashCode(id);
         result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(interfaceName);
-        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(attrs);
-        result = prime * result + java.util.Arrays.deepHashCode(addrs);
+        result = prime * result + java.util.Arrays.deepHashCode(addresses);
+        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(attributes);
         result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(attachments);
         return result;
     }
diff --git a/java/generated-src/io/v/mojo/discovery/Closer.java b/java/generated-src/io/v/mojo/discovery/Closer.java
new file mode 100644
index 0000000..33d8818
--- /dev/null
+++ b/java/generated-src/io/v/mojo/discovery/Closer.java
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by:
+//     mojo/public/tools/bindings/mojom_bindings_generator.py
+// For:
+//     mojom/vanadium/discovery.mojom
+//
+
+package io.v.mojo.discovery;
+
+public interface Closer extends org.chromium.mojo.bindings.Interface {
+
+    public interface Proxy extends Closer, org.chromium.mojo.bindings.Interface.Proxy {
+    }
+
+    Manager<Closer, Closer.Proxy> MANAGER = Closer_Internal.MANAGER;
+
+    void close(CloseResponse callback);
+    interface CloseResponse extends org.chromium.mojo.bindings.Callbacks.Callback0 { }
+}
+
diff --git a/java/generated-src/io/v/mojo/discovery/Closer_Internal.java b/java/generated-src/io/v/mojo/discovery/Closer_Internal.java
new file mode 100644
index 0000000..005d2e8
--- /dev/null
+++ b/java/generated-src/io/v/mojo/discovery/Closer_Internal.java
@@ -0,0 +1,290 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by:
+//     mojo/public/tools/bindings/mojom_bindings_generator.py
+// For:
+//     mojom/vanadium/discovery.mojom
+//
+
+package io.v.mojo.discovery;
+
+class Closer_Internal {
+
+    public static final org.chromium.mojo.bindings.Interface.Manager<Closer, Closer.Proxy> MANAGER =
+            new org.chromium.mojo.bindings.Interface.Manager<Closer, Closer.Proxy>() {
+    
+        public int getVersion() {
+          return 0;
+        }
+    
+        public Proxy buildProxy(org.chromium.mojo.system.Core core,
+                                org.chromium.mojo.bindings.MessageReceiverWithResponder messageReceiver) {
+            return new Proxy(core, messageReceiver);
+        }
+    
+        public Stub buildStub(org.chromium.mojo.system.Core core, Closer impl) {
+            return new Stub(core, impl);
+        }
+    
+        public Closer[] buildArray(int size) {
+          return new Closer[size];
+        }
+    };
+
+    private static final int CLOSE_ORDINAL = 0;
+
+    static final class Proxy extends org.chromium.mojo.bindings.Interface.AbstractProxy implements Closer.Proxy {
+
+        Proxy(org.chromium.mojo.system.Core core,
+              org.chromium.mojo.bindings.MessageReceiverWithResponder messageReceiver) {
+            super(core, messageReceiver);
+        }
+
+        @Override
+        public void close(CloseResponse callback) {
+            CloserCloseParams _message = new CloserCloseParams();
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    CLOSE_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new CloserCloseResponseParamsForwardToCallback(callback));
+        }
+
+    }
+
+    static final class Stub extends org.chromium.mojo.bindings.Interface.Stub<Closer> {
+
+        Stub(org.chromium.mojo.system.Core core, Closer impl) {
+            super(core, impl);
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(org.chromium.mojo.bindings.MessageHeader.NO_FLAG)) {
+                    return false;
+                }
+                switch(header.getType()) {
+                    case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_OR_CLOSE_PIPE_MESSAGE_ID:
+                        return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRunOrClosePipe(
+                                Closer_Internal.MANAGER, messageWithHeader);
+                    default:
+                        return false;
+                }
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                System.err.println(e.toString());
+                return false;
+            }
+        }
+
+        @Override
+        public boolean acceptWithResponder(org.chromium.mojo.bindings.Message message, org.chromium.mojo.bindings.MessageReceiver receiver) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                switch(header.getType()) {
+                    case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_MESSAGE_ID:
+                        return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRun(
+                                getCore(), Closer_Internal.MANAGER, messageWithHeader, receiver);
+                    case CLOSE_ORDINAL: {
+                        CloserCloseParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().close(new CloserCloseResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    default:
+                        return false;
+                }
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                System.err.println(e.toString());
+                return false;
+            }
+        }
+    }
+
+    static final class CloserCloseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 8;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(8, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        private CloserCloseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public CloserCloseParams() {
+            this(0);
+        }
+    
+        public static CloserCloseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static CloserCloseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            CloserCloseParams result = new CloserCloseParams(mainDataHeader.elementsOrVersion);
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            return result;
+        }
+    }
+
+    static final class CloserCloseResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 8;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(8, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        private CloserCloseResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public CloserCloseResponseParams() {
+            this(0);
+        }
+    
+        public static CloserCloseResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static CloserCloseResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            CloserCloseResponseParams result = new CloserCloseResponseParams(mainDataHeader.elementsOrVersion);
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            return result;
+        }
+    }
+
+    static class CloserCloseResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Closer.CloseResponse mCallback;
+
+        CloserCloseResponseParamsForwardToCallback(Closer.CloseResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(CLOSE_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                mCallback.call();
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class CloserCloseResponseParamsProxyToResponder implements Closer.CloseResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        CloserCloseResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call() {
+            CloserCloseResponseParams _response = new CloserCloseResponseParams();
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    CLOSE_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+}
+
diff --git a/java/generated-src/io/v/mojo/discovery/Discovery.java b/java/generated-src/io/v/mojo/discovery/Discovery.java
index 257529c..204ee07 100644
--- a/java/generated-src/io/v/mojo/discovery/Discovery.java
+++ b/java/generated-src/io/v/mojo/discovery/Discovery.java
@@ -17,16 +17,10 @@
 
     NamedManager<Discovery, Discovery.Proxy> MANAGER = Discovery_Internal.MANAGER;
 
-    void startAdvertising(Service service, String[] visibility, StartAdvertisingResponse callback);
-    interface StartAdvertisingResponse extends org.chromium.mojo.bindings.Callbacks.Callback2<String, Error> { }
+    void advertise(Advertisement ad, String[] visibility, AdvertiseResponse callback);
+    interface AdvertiseResponse extends org.chromium.mojo.bindings.Callbacks.Callback3<byte[], Closer, Error> { }
 
-    void stopAdvertising(String instanceId, StopAdvertisingResponse callback);
-    interface StopAdvertisingResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<Error> { }
-
-    void startScan(String query, ScanHandler handler, StartScanResponse callback);
-    interface StartScanResponse extends org.chromium.mojo.bindings.Callbacks.Callback2<Integer, Error> { }
-
-    void stopScan(int scanId, StopScanResponse callback);
-    interface StopScanResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<Error> { }
+    void scan(String query, ScanHandler handler, ScanResponse callback);
+    interface ScanResponse extends org.chromium.mojo.bindings.Callbacks.Callback2<Closer, Error> { }
 }
 
diff --git a/java/generated-src/io/v/mojo/discovery/Discovery_Internal.java b/java/generated-src/io/v/mojo/discovery/Discovery_Internal.java
index 1728856..3b9d0e0 100644
--- a/java/generated-src/io/v/mojo/discovery/Discovery_Internal.java
+++ b/java/generated-src/io/v/mojo/discovery/Discovery_Internal.java
@@ -37,10 +37,8 @@
         }
     };
 
-    private static final int START_ADVERTISING_ORDINAL = 0;
-    private static final int STOP_ADVERTISING_ORDINAL = 1;
-    private static final int START_SCAN_ORDINAL = 2;
-    private static final int STOP_SCAN_ORDINAL = 3;
+    private static final int ADVERTISE_ORDINAL = 0;
+    private static final int SCAN_ORDINAL = 1;
 
     static final class Proxy extends org.chromium.mojo.bindings.Interface.AbstractProxy implements Discovery.Proxy {
 
@@ -50,61 +48,33 @@
         }
 
         @Override
-        public void startAdvertising(Service service, String[] visibility, StartAdvertisingResponse callback) {
-            DiscoveryStartAdvertisingParams _message = new DiscoveryStartAdvertisingParams();
-            _message.service = service;
+        public void advertise(Advertisement ad, String[] visibility, AdvertiseResponse callback) {
+            DiscoveryAdvertiseParams _message = new DiscoveryAdvertiseParams();
+            _message.ad = ad;
             _message.visibility = visibility;
             getProxyHandler().getMessageReceiver().acceptWithResponder(
                     _message.serializeWithHeader(
                             getProxyHandler().getCore(),
                             new org.chromium.mojo.bindings.MessageHeader(
-                                    START_ADVERTISING_ORDINAL,
+                                    ADVERTISE_ORDINAL,
                                     org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
                                     0)),
-                    new DiscoveryStartAdvertisingResponseParamsForwardToCallback(callback));
+                    new DiscoveryAdvertiseResponseParamsForwardToCallback(callback));
         }
 
         @Override
-        public void stopAdvertising(String instanceId, StopAdvertisingResponse callback) {
-            DiscoveryStopAdvertisingParams _message = new DiscoveryStopAdvertisingParams();
-            _message.instanceId = instanceId;
-            getProxyHandler().getMessageReceiver().acceptWithResponder(
-                    _message.serializeWithHeader(
-                            getProxyHandler().getCore(),
-                            new org.chromium.mojo.bindings.MessageHeader(
-                                    STOP_ADVERTISING_ORDINAL,
-                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
-                                    0)),
-                    new DiscoveryStopAdvertisingResponseParamsForwardToCallback(callback));
-        }
-
-        @Override
-        public void startScan(String query, ScanHandler handler, StartScanResponse callback) {
-            DiscoveryStartScanParams _message = new DiscoveryStartScanParams();
+        public void scan(String query, ScanHandler handler, ScanResponse callback) {
+            DiscoveryScanParams _message = new DiscoveryScanParams();
             _message.query = query;
             _message.handler = handler;
             getProxyHandler().getMessageReceiver().acceptWithResponder(
                     _message.serializeWithHeader(
                             getProxyHandler().getCore(),
                             new org.chromium.mojo.bindings.MessageHeader(
-                                    START_SCAN_ORDINAL,
+                                    SCAN_ORDINAL,
                                     org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
                                     0)),
-                    new DiscoveryStartScanResponseParamsForwardToCallback(callback));
-        }
-
-        @Override
-        public void stopScan(int scanId, StopScanResponse callback) {
-            DiscoveryStopScanParams _message = new DiscoveryStopScanParams();
-            _message.scanId = scanId;
-            getProxyHandler().getMessageReceiver().acceptWithResponder(
-                    _message.serializeWithHeader(
-                            getProxyHandler().getCore(),
-                            new org.chromium.mojo.bindings.MessageHeader(
-                                    STOP_SCAN_ORDINAL,
-                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
-                                    0)),
-                    new DiscoveryStopScanResponseParamsForwardToCallback(callback));
+                    new DiscoveryScanResponseParamsForwardToCallback(callback));
         }
 
     }
@@ -150,28 +120,16 @@
                     case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_MESSAGE_ID:
                         return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRun(
                                 getCore(), Discovery_Internal.MANAGER, messageWithHeader, receiver);
-                    case START_ADVERTISING_ORDINAL: {
-                        DiscoveryStartAdvertisingParams data =
-                                DiscoveryStartAdvertisingParams.deserialize(messageWithHeader.getPayload());
-                        getImpl().startAdvertising(data.service, data.visibility, new DiscoveryStartAdvertisingResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                    case ADVERTISE_ORDINAL: {
+                        DiscoveryAdvertiseParams data =
+                                DiscoveryAdvertiseParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().advertise(data.ad, data.visibility, new DiscoveryAdvertiseResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
                         return true;
                     }
-                    case STOP_ADVERTISING_ORDINAL: {
-                        DiscoveryStopAdvertisingParams data =
-                                DiscoveryStopAdvertisingParams.deserialize(messageWithHeader.getPayload());
-                        getImpl().stopAdvertising(data.instanceId, new DiscoveryStopAdvertisingResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
-                        return true;
-                    }
-                    case START_SCAN_ORDINAL: {
-                        DiscoveryStartScanParams data =
-                                DiscoveryStartScanParams.deserialize(messageWithHeader.getPayload());
-                        getImpl().startScan(data.query, data.handler, new DiscoveryStartScanResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
-                        return true;
-                    }
-                    case STOP_SCAN_ORDINAL: {
-                        DiscoveryStopScanParams data =
-                                DiscoveryStopScanParams.deserialize(messageWithHeader.getPayload());
-                        getImpl().stopScan(data.scanId, new DiscoveryStopScanResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                    case SCAN_ORDINAL: {
+                        DiscoveryScanParams data =
+                                DiscoveryScanParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().scan(data.query, data.handler, new DiscoveryScanResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
                         return true;
                     }
                     default:
@@ -184,37 +142,37 @@
         }
     }
 
-    static final class DiscoveryStartAdvertisingParams extends org.chromium.mojo.bindings.Struct {
+    static final class DiscoveryAdvertiseParams extends org.chromium.mojo.bindings.Struct {
     
         private static final int STRUCT_SIZE = 24;
         private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(24, 0)};
         private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
     
-        public Service service;
+        public Advertisement ad;
         public String[] visibility;
     
-        private DiscoveryStartAdvertisingParams(int version) {
+        private DiscoveryAdvertiseParams(int version) {
             super(STRUCT_SIZE, version);
         }
     
-        public DiscoveryStartAdvertisingParams() {
+        public DiscoveryAdvertiseParams() {
             this(0);
         }
     
-        public static DiscoveryStartAdvertisingParams deserialize(org.chromium.mojo.bindings.Message message) {
+        public static DiscoveryAdvertiseParams deserialize(org.chromium.mojo.bindings.Message message) {
             return decode(new org.chromium.mojo.bindings.Decoder(message));
         }
     
         @SuppressWarnings("unchecked")
-        public static DiscoveryStartAdvertisingParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+        public static DiscoveryAdvertiseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
             if (decoder0 == null) {
                 return null;
             }
             org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStartAdvertisingParams result = new DiscoveryStartAdvertisingParams(mainDataHeader.elementsOrVersion);
+            DiscoveryAdvertiseParams result = new DiscoveryAdvertiseParams(mainDataHeader.elementsOrVersion);
             if (mainDataHeader.elementsOrVersion >= 0) {
                 org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(8, false);
-                result.service = Service.decode(decoder1);
+                result.ad = Advertisement.decode(decoder1);
             }
             if (mainDataHeader.elementsOrVersion >= 0) {
                 org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(16, true);
@@ -235,7 +193,7 @@
         @Override
         protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
             org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(service, 8, false);
+            encoder0.encode(ad, 8, false);
             if (visibility == null) {
                 encoder0.encodeNullPointer(16, true);
             } else {
@@ -257,8 +215,8 @@
                 return false;
             if (getClass() != object.getClass())
                 return false;
-            DiscoveryStartAdvertisingParams other = (DiscoveryStartAdvertisingParams) object;
-            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.service, other.service))
+            DiscoveryAdvertiseParams other = (DiscoveryAdvertiseParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.ad, other.ad))
                 return false;
             if (!java.util.Arrays.deepEquals(this.visibility, other.visibility))
                 return false;
@@ -272,45 +230,49 @@
         public int hashCode() {
             final int prime = 31;
             int result = prime + getClass().hashCode();
-            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(service);
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(ad);
             result = prime * result + java.util.Arrays.deepHashCode(visibility);
             return result;
         }
     }
 
-    static final class DiscoveryStartAdvertisingResponseParams extends org.chromium.mojo.bindings.Struct {
+    static final class DiscoveryAdvertiseResponseParams extends org.chromium.mojo.bindings.Struct {
     
-        private static final int STRUCT_SIZE = 24;
-        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(24, 0)};
+        private static final int STRUCT_SIZE = 32;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(32, 0)};
         private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
     
-        public String instanceId;
+        public byte[] instanceId;
+        public Closer closer;
         public Error err;
     
-        private DiscoveryStartAdvertisingResponseParams(int version) {
+        private DiscoveryAdvertiseResponseParams(int version) {
             super(STRUCT_SIZE, version);
         }
     
-        public DiscoveryStartAdvertisingResponseParams() {
+        public DiscoveryAdvertiseResponseParams() {
             this(0);
         }
     
-        public static DiscoveryStartAdvertisingResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+        public static DiscoveryAdvertiseResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
             return decode(new org.chromium.mojo.bindings.Decoder(message));
         }
     
         @SuppressWarnings("unchecked")
-        public static DiscoveryStartAdvertisingResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+        public static DiscoveryAdvertiseResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
             if (decoder0 == null) {
                 return null;
             }
             org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStartAdvertisingResponseParams result = new DiscoveryStartAdvertisingResponseParams(mainDataHeader.elementsOrVersion);
+            DiscoveryAdvertiseResponseParams result = new DiscoveryAdvertiseResponseParams(mainDataHeader.elementsOrVersion);
             if (mainDataHeader.elementsOrVersion >= 0) {
-                result.instanceId = decoder0.readString(8, false);
+                result.instanceId = decoder0.readBytes(8, org.chromium.mojo.bindings.BindingsHelper.ARRAY_NULLABLE, 16);
             }
             if (mainDataHeader.elementsOrVersion >= 0) {
-                org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(16, true);
+                result.closer = decoder0.readServiceInterface(16, true, Closer.MANAGER);
+            }
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(24, true);
                 result.err = Error.decode(decoder1);
             }
             return result;
@@ -320,8 +282,9 @@
         @Override
         protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
             org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(instanceId, 8, false);
-            encoder0.encode(err, 16, true);
+            encoder0.encode(instanceId, 8, org.chromium.mojo.bindings.BindingsHelper.ARRAY_NULLABLE, 16);
+            encoder0.encode(closer, 16, true, Closer.MANAGER);
+            encoder0.encode(err, 24, true);
         }
     
         /**
@@ -335,8 +298,10 @@
                 return false;
             if (getClass() != object.getClass())
                 return false;
-            DiscoveryStartAdvertisingResponseParams other = (DiscoveryStartAdvertisingResponseParams) object;
-            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.instanceId, other.instanceId))
+            DiscoveryAdvertiseResponseParams other = (DiscoveryAdvertiseResponseParams) object;
+            if (!java.util.Arrays.equals(this.instanceId, other.instanceId))
+                return false;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.closer, other.closer))
                 return false;
             if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.err, other.err))
                 return false;
@@ -350,17 +315,18 @@
         public int hashCode() {
             final int prime = 31;
             int result = prime + getClass().hashCode();
-            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(instanceId);
+            result = prime * result + java.util.Arrays.hashCode(instanceId);
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(closer);
             result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(err);
             return result;
         }
     }
 
-    static class DiscoveryStartAdvertisingResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+    static class DiscoveryAdvertiseResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
             implements org.chromium.mojo.bindings.MessageReceiver {
-        private final Discovery.StartAdvertisingResponse mCallback;
+        private final Discovery.AdvertiseResponse mCallback;
 
-        DiscoveryStartAdvertisingResponseParamsForwardToCallback(Discovery.StartAdvertisingResponse callback) {
+        DiscoveryAdvertiseResponseParamsForwardToCallback(Discovery.AdvertiseResponse callback) {
             this.mCallback = callback;
         }
 
@@ -370,12 +336,12 @@
                 org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
                         message.asServiceMessage();
                 org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
-                if (!header.validateHeader(START_ADVERTISING_ORDINAL,
+                if (!header.validateHeader(ADVERTISE_ORDINAL,
                                            org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
                     return false;
                 }
-                DiscoveryStartAdvertisingResponseParams response = DiscoveryStartAdvertisingResponseParams.deserialize(messageWithHeader.getPayload());
-                mCallback.call(response.instanceId, response.err);
+                DiscoveryAdvertiseResponseParams response = DiscoveryAdvertiseResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.instanceId, response.closer, response.err);
                 return true;
             } catch (org.chromium.mojo.bindings.DeserializationException e) {
                 return false;
@@ -383,13 +349,13 @@
         }
     }
 
-    static class DiscoveryStartAdvertisingResponseParamsProxyToResponder implements Discovery.StartAdvertisingResponse {
+    static class DiscoveryAdvertiseResponseParamsProxyToResponder implements Discovery.AdvertiseResponse {
 
         private final org.chromium.mojo.system.Core mCore;
         private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
         private final long mRequestId;
 
-        DiscoveryStartAdvertisingResponseParamsProxyToResponder(
+        DiscoveryAdvertiseResponseParamsProxyToResponder(
                 org.chromium.mojo.system.Core core,
                 org.chromium.mojo.bindings.MessageReceiver messageReceiver,
                 long requestId) {
@@ -399,218 +365,23 @@
         }
 
         @Override
-        public void call(String instanceId, Error err) {
-            DiscoveryStartAdvertisingResponseParams _response = new DiscoveryStartAdvertisingResponseParams();
+        public void call(byte[] instanceId, Closer closer, Error err) {
+            DiscoveryAdvertiseResponseParams _response = new DiscoveryAdvertiseResponseParams();
             _response.instanceId = instanceId;
+            _response.closer = closer;
             _response.err = err;
             org.chromium.mojo.bindings.ServiceMessage _message =
                     _response.serializeWithHeader(
                             mCore,
                             new org.chromium.mojo.bindings.MessageHeader(
-                                    START_ADVERTISING_ORDINAL,
+                                    ADVERTISE_ORDINAL,
                                     org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
                                     mRequestId));
             mMessageReceiver.accept(_message);
         }
     }
 
-    static final class DiscoveryStopAdvertisingParams extends org.chromium.mojo.bindings.Struct {
-    
-        private static final int STRUCT_SIZE = 16;
-        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
-        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
-    
-        public String instanceId;
-    
-        private DiscoveryStopAdvertisingParams(int version) {
-            super(STRUCT_SIZE, version);
-        }
-    
-        public DiscoveryStopAdvertisingParams() {
-            this(0);
-        }
-    
-        public static DiscoveryStopAdvertisingParams deserialize(org.chromium.mojo.bindings.Message message) {
-            return decode(new org.chromium.mojo.bindings.Decoder(message));
-        }
-    
-        @SuppressWarnings("unchecked")
-        public static DiscoveryStopAdvertisingParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
-            if (decoder0 == null) {
-                return null;
-            }
-            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStopAdvertisingParams result = new DiscoveryStopAdvertisingParams(mainDataHeader.elementsOrVersion);
-            if (mainDataHeader.elementsOrVersion >= 0) {
-                result.instanceId = decoder0.readString(8, false);
-            }
-            return result;
-        }
-    
-        @SuppressWarnings("unchecked")
-        @Override
-        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
-            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(instanceId, 8, false);
-        }
-    
-        /**
-         * @see Object#equals(Object)
-         */
-        @Override
-        public boolean equals(Object object) {
-            if (object == this)
-                return true;
-            if (object == null)
-                return false;
-            if (getClass() != object.getClass())
-                return false;
-            DiscoveryStopAdvertisingParams other = (DiscoveryStopAdvertisingParams) object;
-            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.instanceId, other.instanceId))
-                return false;
-            return true;
-        }
-    
-        /**
-         * @see Object#hashCode()
-         */
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = prime + getClass().hashCode();
-            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(instanceId);
-            return result;
-        }
-    }
-
-    static final class DiscoveryStopAdvertisingResponseParams extends org.chromium.mojo.bindings.Struct {
-    
-        private static final int STRUCT_SIZE = 16;
-        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
-        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
-    
-        public Error err;
-    
-        private DiscoveryStopAdvertisingResponseParams(int version) {
-            super(STRUCT_SIZE, version);
-        }
-    
-        public DiscoveryStopAdvertisingResponseParams() {
-            this(0);
-        }
-    
-        public static DiscoveryStopAdvertisingResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
-            return decode(new org.chromium.mojo.bindings.Decoder(message));
-        }
-    
-        @SuppressWarnings("unchecked")
-        public static DiscoveryStopAdvertisingResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
-            if (decoder0 == null) {
-                return null;
-            }
-            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStopAdvertisingResponseParams result = new DiscoveryStopAdvertisingResponseParams(mainDataHeader.elementsOrVersion);
-            if (mainDataHeader.elementsOrVersion >= 0) {
-                org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(8, true);
-                result.err = Error.decode(decoder1);
-            }
-            return result;
-        }
-    
-        @SuppressWarnings("unchecked")
-        @Override
-        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
-            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(err, 8, true);
-        }
-    
-        /**
-         * @see Object#equals(Object)
-         */
-        @Override
-        public boolean equals(Object object) {
-            if (object == this)
-                return true;
-            if (object == null)
-                return false;
-            if (getClass() != object.getClass())
-                return false;
-            DiscoveryStopAdvertisingResponseParams other = (DiscoveryStopAdvertisingResponseParams) object;
-            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.err, other.err))
-                return false;
-            return true;
-        }
-    
-        /**
-         * @see Object#hashCode()
-         */
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = prime + getClass().hashCode();
-            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(err);
-            return result;
-        }
-    }
-
-    static class DiscoveryStopAdvertisingResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
-            implements org.chromium.mojo.bindings.MessageReceiver {
-        private final Discovery.StopAdvertisingResponse mCallback;
-
-        DiscoveryStopAdvertisingResponseParamsForwardToCallback(Discovery.StopAdvertisingResponse callback) {
-            this.mCallback = callback;
-        }
-
-        @Override
-        public boolean accept(org.chromium.mojo.bindings.Message message) {
-            try {
-                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
-                        message.asServiceMessage();
-                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
-                if (!header.validateHeader(STOP_ADVERTISING_ORDINAL,
-                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
-                    return false;
-                }
-                DiscoveryStopAdvertisingResponseParams response = DiscoveryStopAdvertisingResponseParams.deserialize(messageWithHeader.getPayload());
-                mCallback.call(response.err);
-                return true;
-            } catch (org.chromium.mojo.bindings.DeserializationException e) {
-                return false;
-            }
-        }
-    }
-
-    static class DiscoveryStopAdvertisingResponseParamsProxyToResponder implements Discovery.StopAdvertisingResponse {
-
-        private final org.chromium.mojo.system.Core mCore;
-        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
-        private final long mRequestId;
-
-        DiscoveryStopAdvertisingResponseParamsProxyToResponder(
-                org.chromium.mojo.system.Core core,
-                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
-                long requestId) {
-            mCore = core;
-            mMessageReceiver = messageReceiver;
-            mRequestId = requestId;
-        }
-
-        @Override
-        public void call(Error err) {
-            DiscoveryStopAdvertisingResponseParams _response = new DiscoveryStopAdvertisingResponseParams();
-            _response.err = err;
-            org.chromium.mojo.bindings.ServiceMessage _message =
-                    _response.serializeWithHeader(
-                            mCore,
-                            new org.chromium.mojo.bindings.MessageHeader(
-                                    STOP_ADVERTISING_ORDINAL,
-                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
-                                    mRequestId));
-            mMessageReceiver.accept(_message);
-        }
-    }
-
-    static final class DiscoveryStartScanParams extends org.chromium.mojo.bindings.Struct {
+    static final class DiscoveryScanParams extends org.chromium.mojo.bindings.Struct {
     
         private static final int STRUCT_SIZE = 24;
         private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(24, 0)};
@@ -619,25 +390,25 @@
         public String query;
         public ScanHandler handler;
     
-        private DiscoveryStartScanParams(int version) {
+        private DiscoveryScanParams(int version) {
             super(STRUCT_SIZE, version);
         }
     
-        public DiscoveryStartScanParams() {
+        public DiscoveryScanParams() {
             this(0);
         }
     
-        public static DiscoveryStartScanParams deserialize(org.chromium.mojo.bindings.Message message) {
+        public static DiscoveryScanParams deserialize(org.chromium.mojo.bindings.Message message) {
             return decode(new org.chromium.mojo.bindings.Decoder(message));
         }
     
         @SuppressWarnings("unchecked")
-        public static DiscoveryStartScanParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+        public static DiscoveryScanParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
             if (decoder0 == null) {
                 return null;
             }
             org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStartScanParams result = new DiscoveryStartScanParams(mainDataHeader.elementsOrVersion);
+            DiscoveryScanParams result = new DiscoveryScanParams(mainDataHeader.elementsOrVersion);
             if (mainDataHeader.elementsOrVersion >= 0) {
                 result.query = decoder0.readString(8, false);
             }
@@ -666,7 +437,7 @@
                 return false;
             if (getClass() != object.getClass())
                 return false;
-            DiscoveryStartScanParams other = (DiscoveryStartScanParams) object;
+            DiscoveryScanParams other = (DiscoveryScanParams) object;
             if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.query, other.query))
                 return false;
             if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.handler, other.handler))
@@ -687,36 +458,36 @@
         }
     }
 
-    static final class DiscoveryStartScanResponseParams extends org.chromium.mojo.bindings.Struct {
+    static final class DiscoveryScanResponseParams extends org.chromium.mojo.bindings.Struct {
     
         private static final int STRUCT_SIZE = 24;
         private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(24, 0)};
         private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
     
-        public int scanId;
+        public Closer closer;
         public Error err;
     
-        private DiscoveryStartScanResponseParams(int version) {
+        private DiscoveryScanResponseParams(int version) {
             super(STRUCT_SIZE, version);
         }
     
-        public DiscoveryStartScanResponseParams() {
+        public DiscoveryScanResponseParams() {
             this(0);
         }
     
-        public static DiscoveryStartScanResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+        public static DiscoveryScanResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
             return decode(new org.chromium.mojo.bindings.Decoder(message));
         }
     
         @SuppressWarnings("unchecked")
-        public static DiscoveryStartScanResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+        public static DiscoveryScanResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
             if (decoder0 == null) {
                 return null;
             }
             org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStartScanResponseParams result = new DiscoveryStartScanResponseParams(mainDataHeader.elementsOrVersion);
+            DiscoveryScanResponseParams result = new DiscoveryScanResponseParams(mainDataHeader.elementsOrVersion);
             if (mainDataHeader.elementsOrVersion >= 0) {
-                result.scanId = decoder0.readInt(8);
+                result.closer = decoder0.readServiceInterface(8, true, Closer.MANAGER);
             }
             if (mainDataHeader.elementsOrVersion >= 0) {
                 org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(16, true);
@@ -729,7 +500,7 @@
         @Override
         protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
             org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(scanId, 8);
+            encoder0.encode(closer, 8, true, Closer.MANAGER);
             encoder0.encode(err, 16, true);
         }
     
@@ -744,8 +515,8 @@
                 return false;
             if (getClass() != object.getClass())
                 return false;
-            DiscoveryStartScanResponseParams other = (DiscoveryStartScanResponseParams) object;
-            if (this.scanId != other.scanId)
+            DiscoveryScanResponseParams other = (DiscoveryScanResponseParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.closer, other.closer))
                 return false;
             if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.err, other.err))
                 return false;
@@ -759,17 +530,17 @@
         public int hashCode() {
             final int prime = 31;
             int result = prime + getClass().hashCode();
-            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(scanId);
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(closer);
             result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(err);
             return result;
         }
     }
 
-    static class DiscoveryStartScanResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+    static class DiscoveryScanResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
             implements org.chromium.mojo.bindings.MessageReceiver {
-        private final Discovery.StartScanResponse mCallback;
+        private final Discovery.ScanResponse mCallback;
 
-        DiscoveryStartScanResponseParamsForwardToCallback(Discovery.StartScanResponse callback) {
+        DiscoveryScanResponseParamsForwardToCallback(Discovery.ScanResponse callback) {
             this.mCallback = callback;
         }
 
@@ -779,12 +550,12 @@
                 org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
                         message.asServiceMessage();
                 org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
-                if (!header.validateHeader(START_SCAN_ORDINAL,
+                if (!header.validateHeader(SCAN_ORDINAL,
                                            org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
                     return false;
                 }
-                DiscoveryStartScanResponseParams response = DiscoveryStartScanResponseParams.deserialize(messageWithHeader.getPayload());
-                mCallback.call(response.scanId, response.err);
+                DiscoveryScanResponseParams response = DiscoveryScanResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.closer, response.err);
                 return true;
             } catch (org.chromium.mojo.bindings.DeserializationException e) {
                 return false;
@@ -792,13 +563,13 @@
         }
     }
 
-    static class DiscoveryStartScanResponseParamsProxyToResponder implements Discovery.StartScanResponse {
+    static class DiscoveryScanResponseParamsProxyToResponder implements Discovery.ScanResponse {
 
         private final org.chromium.mojo.system.Core mCore;
         private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
         private final long mRequestId;
 
-        DiscoveryStartScanResponseParamsProxyToResponder(
+        DiscoveryScanResponseParamsProxyToResponder(
                 org.chromium.mojo.system.Core core,
                 org.chromium.mojo.bindings.MessageReceiver messageReceiver,
                 long requestId) {
@@ -808,211 +579,15 @@
         }
 
         @Override
-        public void call(Integer scanId, Error err) {
-            DiscoveryStartScanResponseParams _response = new DiscoveryStartScanResponseParams();
-            _response.scanId = scanId;
+        public void call(Closer closer, Error err) {
+            DiscoveryScanResponseParams _response = new DiscoveryScanResponseParams();
+            _response.closer = closer;
             _response.err = err;
             org.chromium.mojo.bindings.ServiceMessage _message =
                     _response.serializeWithHeader(
                             mCore,
                             new org.chromium.mojo.bindings.MessageHeader(
-                                    START_SCAN_ORDINAL,
-                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
-                                    mRequestId));
-            mMessageReceiver.accept(_message);
-        }
-    }
-
-    static final class DiscoveryStopScanParams extends org.chromium.mojo.bindings.Struct {
-    
-        private static final int STRUCT_SIZE = 16;
-        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
-        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
-    
-        public int scanId;
-    
-        private DiscoveryStopScanParams(int version) {
-            super(STRUCT_SIZE, version);
-        }
-    
-        public DiscoveryStopScanParams() {
-            this(0);
-        }
-    
-        public static DiscoveryStopScanParams deserialize(org.chromium.mojo.bindings.Message message) {
-            return decode(new org.chromium.mojo.bindings.Decoder(message));
-        }
-    
-        @SuppressWarnings("unchecked")
-        public static DiscoveryStopScanParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
-            if (decoder0 == null) {
-                return null;
-            }
-            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStopScanParams result = new DiscoveryStopScanParams(mainDataHeader.elementsOrVersion);
-            if (mainDataHeader.elementsOrVersion >= 0) {
-                result.scanId = decoder0.readInt(8);
-            }
-            return result;
-        }
-    
-        @SuppressWarnings("unchecked")
-        @Override
-        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
-            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(scanId, 8);
-        }
-    
-        /**
-         * @see Object#equals(Object)
-         */
-        @Override
-        public boolean equals(Object object) {
-            if (object == this)
-                return true;
-            if (object == null)
-                return false;
-            if (getClass() != object.getClass())
-                return false;
-            DiscoveryStopScanParams other = (DiscoveryStopScanParams) object;
-            if (this.scanId != other.scanId)
-                return false;
-            return true;
-        }
-    
-        /**
-         * @see Object#hashCode()
-         */
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = prime + getClass().hashCode();
-            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(scanId);
-            return result;
-        }
-    }
-
-    static final class DiscoveryStopScanResponseParams extends org.chromium.mojo.bindings.Struct {
-    
-        private static final int STRUCT_SIZE = 16;
-        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
-        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
-    
-        public Error err;
-    
-        private DiscoveryStopScanResponseParams(int version) {
-            super(STRUCT_SIZE, version);
-        }
-    
-        public DiscoveryStopScanResponseParams() {
-            this(0);
-        }
-    
-        public static DiscoveryStopScanResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
-            return decode(new org.chromium.mojo.bindings.Decoder(message));
-        }
-    
-        @SuppressWarnings("unchecked")
-        public static DiscoveryStopScanResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
-            if (decoder0 == null) {
-                return null;
-            }
-            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            DiscoveryStopScanResponseParams result = new DiscoveryStopScanResponseParams(mainDataHeader.elementsOrVersion);
-            if (mainDataHeader.elementsOrVersion >= 0) {
-                org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(8, true);
-                result.err = Error.decode(decoder1);
-            }
-            return result;
-        }
-    
-        @SuppressWarnings("unchecked")
-        @Override
-        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
-            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(err, 8, true);
-        }
-    
-        /**
-         * @see Object#equals(Object)
-         */
-        @Override
-        public boolean equals(Object object) {
-            if (object == this)
-                return true;
-            if (object == null)
-                return false;
-            if (getClass() != object.getClass())
-                return false;
-            DiscoveryStopScanResponseParams other = (DiscoveryStopScanResponseParams) object;
-            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.err, other.err))
-                return false;
-            return true;
-        }
-    
-        /**
-         * @see Object#hashCode()
-         */
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = prime + getClass().hashCode();
-            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(err);
-            return result;
-        }
-    }
-
-    static class DiscoveryStopScanResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
-            implements org.chromium.mojo.bindings.MessageReceiver {
-        private final Discovery.StopScanResponse mCallback;
-
-        DiscoveryStopScanResponseParamsForwardToCallback(Discovery.StopScanResponse callback) {
-            this.mCallback = callback;
-        }
-
-        @Override
-        public boolean accept(org.chromium.mojo.bindings.Message message) {
-            try {
-                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
-                        message.asServiceMessage();
-                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
-                if (!header.validateHeader(STOP_SCAN_ORDINAL,
-                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
-                    return false;
-                }
-                DiscoveryStopScanResponseParams response = DiscoveryStopScanResponseParams.deserialize(messageWithHeader.getPayload());
-                mCallback.call(response.err);
-                return true;
-            } catch (org.chromium.mojo.bindings.DeserializationException e) {
-                return false;
-            }
-        }
-    }
-
-    static class DiscoveryStopScanResponseParamsProxyToResponder implements Discovery.StopScanResponse {
-
-        private final org.chromium.mojo.system.Core mCore;
-        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
-        private final long mRequestId;
-
-        DiscoveryStopScanResponseParamsProxyToResponder(
-                org.chromium.mojo.system.Core core,
-                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
-                long requestId) {
-            mCore = core;
-            mMessageReceiver = messageReceiver;
-            mRequestId = requestId;
-        }
-
-        @Override
-        public void call(Error err) {
-            DiscoveryStopScanResponseParams _response = new DiscoveryStopScanResponseParams();
-            _response.err = err;
-            org.chromium.mojo.bindings.ServiceMessage _message =
-                    _response.serializeWithHeader(
-                            mCore,
-                            new org.chromium.mojo.bindings.MessageHeader(
-                                    STOP_SCAN_ORDINAL,
+                                    SCAN_ORDINAL,
                                     org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
                                     mRequestId));
             mMessageReceiver.accept(_message);
diff --git a/java/generated-src/io/v/mojo/discovery/Error.java b/java/generated-src/io/v/mojo/discovery/Error.java
index a401fa9..d13f62b 100644
--- a/java/generated-src/io/v/mojo/discovery/Error.java
+++ b/java/generated-src/io/v/mojo/discovery/Error.java
@@ -17,7 +17,7 @@
     private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
 
     public String id;
-    public int action;
+    public int actionCode;
     public String msg;
 
     private Error(int version) {
@@ -43,7 +43,7 @@
             result.id = decoder0.readString(8, false);
         }
         if (mainDataHeader.elementsOrVersion >= 0) {
-            result.action = decoder0.readInt(16);
+            result.actionCode = decoder0.readInt(16);
         }
         if (mainDataHeader.elementsOrVersion >= 0) {
             result.msg = decoder0.readString(24, false);
@@ -56,7 +56,7 @@
     protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
         org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
         encoder0.encode(id, 8, false);
-        encoder0.encode(action, 16);
+        encoder0.encode(actionCode, 16);
         encoder0.encode(msg, 24, false);
     }
 
@@ -74,7 +74,7 @@
         Error other = (Error) object;
         if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.id, other.id))
             return false;
-        if (this.action != other.action)
+        if (this.actionCode != other.actionCode)
             return false;
         if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.msg, other.msg))
             return false;
@@ -89,7 +89,7 @@
         final int prime = 31;
         int result = prime + getClass().hashCode();
         result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(id);
-        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(action);
+        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(actionCode);
         result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(msg);
         return result;
     }
diff --git a/java/generated-src/io/v/mojo/discovery/ScanHandler.java b/java/generated-src/io/v/mojo/discovery/ScanHandler.java
index 4042b8e..6513d59 100644
--- a/java/generated-src/io/v/mojo/discovery/ScanHandler.java
+++ b/java/generated-src/io/v/mojo/discovery/ScanHandler.java
@@ -15,8 +15,8 @@
     public interface Proxy extends ScanHandler, org.chromium.mojo.bindings.Interface.Proxy {
     }
 
-    NamedManager<ScanHandler, ScanHandler.Proxy> MANAGER = ScanHandler_Internal.MANAGER;
+    Manager<ScanHandler, ScanHandler.Proxy> MANAGER = ScanHandler_Internal.MANAGER;
 
-    void update(ScanUpdate update);
+    void onUpdate(Update update);
 }
 
diff --git a/java/generated-src/io/v/mojo/discovery/ScanHandler_Internal.java b/java/generated-src/io/v/mojo/discovery/ScanHandler_Internal.java
index d3c280d..f29db38 100644
--- a/java/generated-src/io/v/mojo/discovery/ScanHandler_Internal.java
+++ b/java/generated-src/io/v/mojo/discovery/ScanHandler_Internal.java
@@ -12,12 +12,8 @@
 
 class ScanHandler_Internal {
 
-    public static final org.chromium.mojo.bindings.Interface.NamedManager<ScanHandler, ScanHandler.Proxy> MANAGER =
-            new org.chromium.mojo.bindings.Interface.NamedManager<ScanHandler, ScanHandler.Proxy>() {
-    
-        public String getName() {
-            return "v23::discovery::ScanHandler";
-        }
+    public static final org.chromium.mojo.bindings.Interface.Manager<ScanHandler, ScanHandler.Proxy> MANAGER =
+            new org.chromium.mojo.bindings.Interface.Manager<ScanHandler, ScanHandler.Proxy>() {
     
         public int getVersion() {
           return 0;
@@ -37,7 +33,7 @@
         }
     };
 
-    private static final int UPDATE_ORDINAL = 0;
+    private static final int ON_UPDATE_ORDINAL = 0;
 
     static final class Proxy extends org.chromium.mojo.bindings.Interface.AbstractProxy implements ScanHandler.Proxy {
 
@@ -47,13 +43,13 @@
         }
 
         @Override
-        public void update(ScanUpdate update) {
-            ScanHandlerUpdateParams _message = new ScanHandlerUpdateParams();
+        public void onUpdate(Update update) {
+            ScanHandlerOnUpdateParams _message = new ScanHandlerOnUpdateParams();
             _message.update = update;
             getProxyHandler().getMessageReceiver().accept(
                     _message.serializeWithHeader(
                             getProxyHandler().getCore(),
-                            new org.chromium.mojo.bindings.MessageHeader(UPDATE_ORDINAL)));
+                            new org.chromium.mojo.bindings.MessageHeader(ON_UPDATE_ORDINAL)));
         }
 
     }
@@ -77,10 +73,10 @@
                     case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_OR_CLOSE_PIPE_MESSAGE_ID:
                         return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRunOrClosePipe(
                                 ScanHandler_Internal.MANAGER, messageWithHeader);
-                    case UPDATE_ORDINAL: {
-                        ScanHandlerUpdateParams data =
-                                ScanHandlerUpdateParams.deserialize(messageWithHeader.getPayload());
-                        getImpl().update(data.update);
+                    case ON_UPDATE_ORDINAL: {
+                        ScanHandlerOnUpdateParams data =
+                                ScanHandlerOnUpdateParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().onUpdate(data.update);
                         return true;
                     }
                     default:
@@ -115,36 +111,35 @@
         }
     }
 
-    static final class ScanHandlerUpdateParams extends org.chromium.mojo.bindings.Struct {
+    static final class ScanHandlerOnUpdateParams extends org.chromium.mojo.bindings.Struct {
     
         private static final int STRUCT_SIZE = 16;
         private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
         private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
     
-        public ScanUpdate update;
+        public Update update;
     
-        private ScanHandlerUpdateParams(int version) {
+        private ScanHandlerOnUpdateParams(int version) {
             super(STRUCT_SIZE, version);
         }
     
-        public ScanHandlerUpdateParams() {
+        public ScanHandlerOnUpdateParams() {
             this(0);
         }
     
-        public static ScanHandlerUpdateParams deserialize(org.chromium.mojo.bindings.Message message) {
+        public static ScanHandlerOnUpdateParams deserialize(org.chromium.mojo.bindings.Message message) {
             return decode(new org.chromium.mojo.bindings.Decoder(message));
         }
     
         @SuppressWarnings("unchecked")
-        public static ScanHandlerUpdateParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+        public static ScanHandlerOnUpdateParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
             if (decoder0 == null) {
                 return null;
             }
             org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-            ScanHandlerUpdateParams result = new ScanHandlerUpdateParams(mainDataHeader.elementsOrVersion);
+            ScanHandlerOnUpdateParams result = new ScanHandlerOnUpdateParams(mainDataHeader.elementsOrVersion);
             if (mainDataHeader.elementsOrVersion >= 0) {
-                org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(8, false);
-                result.update = ScanUpdate.decode(decoder1);
+                result.update = decoder0.readServiceInterface(8, false, Update.MANAGER);
             }
             return result;
         }
@@ -153,7 +148,7 @@
         @Override
         protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
             org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-            encoder0.encode(update, 8, false);
+            encoder0.encode(update, 8, false, Update.MANAGER);
         }
     
         /**
@@ -167,7 +162,7 @@
                 return false;
             if (getClass() != object.getClass())
                 return false;
-            ScanHandlerUpdateParams other = (ScanHandlerUpdateParams) object;
+            ScanHandlerOnUpdateParams other = (ScanHandlerOnUpdateParams) object;
             if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.update, other.update))
                 return false;
             return true;
diff --git a/java/generated-src/io/v/mojo/discovery/ScanUpdate.java b/java/generated-src/io/v/mojo/discovery/ScanUpdate.java
deleted file mode 100644
index 52471d0..0000000
--- a/java/generated-src/io/v/mojo/discovery/ScanUpdate.java
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is autogenerated by:
-//     mojo/public/tools/bindings/mojom_bindings_generator.py
-// For:
-//     mojom/vanadium/discovery.mojom
-//
-
-package io.v.mojo.discovery;
-
-public final class ScanUpdate extends org.chromium.mojo.bindings.Struct {
-
-    private static final int STRUCT_SIZE = 24;
-    private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(24, 0)};
-    private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
-
-    public Service service;
-    public int updateType;
-
-    private ScanUpdate(int version) {
-        super(STRUCT_SIZE, version);
-    }
-
-    public ScanUpdate() {
-        this(0);
-    }
-
-    public static ScanUpdate deserialize(org.chromium.mojo.bindings.Message message) {
-        return decode(new org.chromium.mojo.bindings.Decoder(message));
-    }
-
-    @SuppressWarnings("unchecked")
-    public static ScanUpdate decode(org.chromium.mojo.bindings.Decoder decoder0) {
-        if (decoder0 == null) {
-            return null;
-        }
-        org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
-        ScanUpdate result = new ScanUpdate(mainDataHeader.elementsOrVersion);
-        if (mainDataHeader.elementsOrVersion >= 0) {
-            org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(8, false);
-            result.service = Service.decode(decoder1);
-        }
-        if (mainDataHeader.elementsOrVersion >= 0) {
-            result.updateType = decoder0.readInt(16);
-        }
-        return result;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
-        org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
-        encoder0.encode(service, 8, false);
-        encoder0.encode(updateType, 16);
-    }
-
-    /**
-     * @see Object#equals(Object)
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (object == this)
-            return true;
-        if (object == null)
-            return false;
-        if (getClass() != object.getClass())
-            return false;
-        ScanUpdate other = (ScanUpdate) object;
-        if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.service, other.service))
-            return false;
-        if (this.updateType != other.updateType)
-            return false;
-        return true;
-    }
-
-    /**
-     * @see Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = prime + getClass().hashCode();
-        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(service);
-        result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(updateType);
-        return result;
-    }
-}
-
diff --git a/java/generated-src/io/v/mojo/discovery/Update.java b/java/generated-src/io/v/mojo/discovery/Update.java
new file mode 100644
index 0000000..5cde12c
--- /dev/null
+++ b/java/generated-src/io/v/mojo/discovery/Update.java
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by:
+//     mojo/public/tools/bindings/mojom_bindings_generator.py
+// For:
+//     mojom/vanadium/discovery.mojom
+//
+
+package io.v.mojo.discovery;
+
+public interface Update extends org.chromium.mojo.bindings.Interface {
+
+    public interface Proxy extends Update, org.chromium.mojo.bindings.Interface.Proxy {
+    }
+
+    Manager<Update, Update.Proxy> MANAGER = Update_Internal.MANAGER;
+
+    void isLost(IsLostResponse callback);
+    interface IsLostResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<Boolean> { }
+
+    void getId(GetIdResponse callback);
+    interface GetIdResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<byte[]> { }
+
+    void getInterfaceName(GetInterfaceNameResponse callback);
+    interface GetInterfaceNameResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<String> { }
+
+    void getAddresses(GetAddressesResponse callback);
+    interface GetAddressesResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<String[]> { }
+
+    void getAttribute(String name, GetAttributeResponse callback);
+    interface GetAttributeResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<String> { }
+
+    void getAttachment(String name, GetAttachmentResponse callback);
+    interface GetAttachmentResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<org.chromium.mojo.system.DataPipe.ConsumerHandle> { }
+
+    void getAdvertisement(GetAdvertisementResponse callback);
+    interface GetAdvertisementResponse extends org.chromium.mojo.bindings.Callbacks.Callback1<Advertisement> { }
+}
+
diff --git a/java/generated-src/io/v/mojo/discovery/UpdateType.java b/java/generated-src/io/v/mojo/discovery/UpdateType.java
deleted file mode 100644
index 7533314..0000000
--- a/java/generated-src/io/v/mojo/discovery/UpdateType.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is autogenerated by:
-//     mojo/public/tools/bindings/mojom_bindings_generator.py
-// For:
-//     mojom/vanadium/discovery.mojom
-//
-
-package io.v.mojo.discovery;
-
-public final class UpdateType {
-
-    public static final int FOUND = (int) (1L);
-    public static final int LOST = FOUND + 1;
-
-    private UpdateType() {}
-
-}
diff --git a/java/generated-src/io/v/mojo/discovery/Update_Internal.java b/java/generated-src/io/v/mojo/discovery/Update_Internal.java
new file mode 100644
index 0000000..506a9f9
--- /dev/null
+++ b/java/generated-src/io/v/mojo/discovery/Update_Internal.java
@@ -0,0 +1,1566 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is autogenerated by:
+//     mojo/public/tools/bindings/mojom_bindings_generator.py
+// For:
+//     mojom/vanadium/discovery.mojom
+//
+
+package io.v.mojo.discovery;
+
+class Update_Internal {
+
+    public static final org.chromium.mojo.bindings.Interface.Manager<Update, Update.Proxy> MANAGER =
+            new org.chromium.mojo.bindings.Interface.Manager<Update, Update.Proxy>() {
+    
+        public int getVersion() {
+          return 0;
+        }
+    
+        public Proxy buildProxy(org.chromium.mojo.system.Core core,
+                                org.chromium.mojo.bindings.MessageReceiverWithResponder messageReceiver) {
+            return new Proxy(core, messageReceiver);
+        }
+    
+        public Stub buildStub(org.chromium.mojo.system.Core core, Update impl) {
+            return new Stub(core, impl);
+        }
+    
+        public Update[] buildArray(int size) {
+          return new Update[size];
+        }
+    };
+
+    private static final int IS_LOST_ORDINAL = 0;
+    private static final int GET_ID_ORDINAL = 1;
+    private static final int GET_INTERFACE_NAME_ORDINAL = 2;
+    private static final int GET_ADDRESSES_ORDINAL = 3;
+    private static final int GET_ATTRIBUTE_ORDINAL = 4;
+    private static final int GET_ATTACHMENT_ORDINAL = 5;
+    private static final int GET_ADVERTISEMENT_ORDINAL = 6;
+
+    static final class Proxy extends org.chromium.mojo.bindings.Interface.AbstractProxy implements Update.Proxy {
+
+        Proxy(org.chromium.mojo.system.Core core,
+              org.chromium.mojo.bindings.MessageReceiverWithResponder messageReceiver) {
+            super(core, messageReceiver);
+        }
+
+        @Override
+        public void isLost(IsLostResponse callback) {
+            UpdateIsLostParams _message = new UpdateIsLostParams();
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    IS_LOST_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new UpdateIsLostResponseParamsForwardToCallback(callback));
+        }
+
+        @Override
+        public void getId(GetIdResponse callback) {
+            UpdateGetIdParams _message = new UpdateGetIdParams();
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ID_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new UpdateGetIdResponseParamsForwardToCallback(callback));
+        }
+
+        @Override
+        public void getInterfaceName(GetInterfaceNameResponse callback) {
+            UpdateGetInterfaceNameParams _message = new UpdateGetInterfaceNameParams();
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_INTERFACE_NAME_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new UpdateGetInterfaceNameResponseParamsForwardToCallback(callback));
+        }
+
+        @Override
+        public void getAddresses(GetAddressesResponse callback) {
+            UpdateGetAddressesParams _message = new UpdateGetAddressesParams();
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ADDRESSES_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new UpdateGetAddressesResponseParamsForwardToCallback(callback));
+        }
+
+        @Override
+        public void getAttribute(String name, GetAttributeResponse callback) {
+            UpdateGetAttributeParams _message = new UpdateGetAttributeParams();
+            _message.name = name;
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ATTRIBUTE_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new UpdateGetAttributeResponseParamsForwardToCallback(callback));
+        }
+
+        @Override
+        public void getAttachment(String name, GetAttachmentResponse callback) {
+            UpdateGetAttachmentParams _message = new UpdateGetAttachmentParams();
+            _message.name = name;
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ATTACHMENT_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new UpdateGetAttachmentResponseParamsForwardToCallback(callback));
+        }
+
+        @Override
+        public void getAdvertisement(GetAdvertisementResponse callback) {
+            UpdateGetAdvertisementParams _message = new UpdateGetAdvertisementParams();
+            getProxyHandler().getMessageReceiver().acceptWithResponder(
+                    _message.serializeWithHeader(
+                            getProxyHandler().getCore(),
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ADVERTISEMENT_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG,
+                                    0)),
+                    new UpdateGetAdvertisementResponseParamsForwardToCallback(callback));
+        }
+
+    }
+
+    static final class Stub extends org.chromium.mojo.bindings.Interface.Stub<Update> {
+
+        Stub(org.chromium.mojo.system.Core core, Update impl) {
+            super(core, impl);
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(org.chromium.mojo.bindings.MessageHeader.NO_FLAG)) {
+                    return false;
+                }
+                switch(header.getType()) {
+                    case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_OR_CLOSE_PIPE_MESSAGE_ID:
+                        return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRunOrClosePipe(
+                                Update_Internal.MANAGER, messageWithHeader);
+                    default:
+                        return false;
+                }
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                System.err.println(e.toString());
+                return false;
+            }
+        }
+
+        @Override
+        public boolean acceptWithResponder(org.chromium.mojo.bindings.Message message, org.chromium.mojo.bindings.MessageReceiver receiver) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(org.chromium.mojo.bindings.MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                switch(header.getType()) {
+                    case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_MESSAGE_ID:
+                        return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRun(
+                                getCore(), Update_Internal.MANAGER, messageWithHeader, receiver);
+                    case IS_LOST_ORDINAL: {
+                        UpdateIsLostParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().isLost(new UpdateIsLostResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    case GET_ID_ORDINAL: {
+                        UpdateGetIdParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().getId(new UpdateGetIdResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    case GET_INTERFACE_NAME_ORDINAL: {
+                        UpdateGetInterfaceNameParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().getInterfaceName(new UpdateGetInterfaceNameResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    case GET_ADDRESSES_ORDINAL: {
+                        UpdateGetAddressesParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().getAddresses(new UpdateGetAddressesResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    case GET_ATTRIBUTE_ORDINAL: {
+                        UpdateGetAttributeParams data =
+                                UpdateGetAttributeParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().getAttribute(data.name, new UpdateGetAttributeResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    case GET_ATTACHMENT_ORDINAL: {
+                        UpdateGetAttachmentParams data =
+                                UpdateGetAttachmentParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().getAttachment(data.name, new UpdateGetAttachmentResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    case GET_ADVERTISEMENT_ORDINAL: {
+                        UpdateGetAdvertisementParams.deserialize(messageWithHeader.getPayload());
+                        getImpl().getAdvertisement(new UpdateGetAdvertisementResponseParamsProxyToResponder(getCore(), receiver, header.getRequestId()));
+                        return true;
+                    }
+                    default:
+                        return false;
+                }
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                System.err.println(e.toString());
+                return false;
+            }
+        }
+    }
+
+    static final class UpdateIsLostParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 8;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(8, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        private UpdateIsLostParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateIsLostParams() {
+            this(0);
+        }
+    
+        public static UpdateIsLostParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateIsLostParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateIsLostParams result = new UpdateIsLostParams(mainDataHeader.elementsOrVersion);
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            return result;
+        }
+    }
+
+    static final class UpdateIsLostResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public boolean lost;
+    
+        private UpdateIsLostResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateIsLostResponseParams() {
+            this(0);
+        }
+    
+        public static UpdateIsLostResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateIsLostResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateIsLostResponseParams result = new UpdateIsLostResponseParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                result.lost = decoder0.readBoolean(8, 0);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(lost, 8, 0);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateIsLostResponseParams other = (UpdateIsLostResponseParams) object;
+            if (this.lost != other.lost)
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(lost);
+            return result;
+        }
+    }
+
+    static class UpdateIsLostResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Update.IsLostResponse mCallback;
+
+        UpdateIsLostResponseParamsForwardToCallback(Update.IsLostResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(IS_LOST_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                UpdateIsLostResponseParams response = UpdateIsLostResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.lost);
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class UpdateIsLostResponseParamsProxyToResponder implements Update.IsLostResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        UpdateIsLostResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call(Boolean lost) {
+            UpdateIsLostResponseParams _response = new UpdateIsLostResponseParams();
+            _response.lost = lost;
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    IS_LOST_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+    static final class UpdateGetIdParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 8;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(8, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        private UpdateGetIdParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetIdParams() {
+            this(0);
+        }
+    
+        public static UpdateGetIdParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetIdParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetIdParams result = new UpdateGetIdParams(mainDataHeader.elementsOrVersion);
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            return result;
+        }
+    }
+
+    static final class UpdateGetIdResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public byte[] id;
+    
+        private UpdateGetIdResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetIdResponseParams() {
+            this(0);
+        }
+    
+        public static UpdateGetIdResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetIdResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetIdResponseParams result = new UpdateGetIdResponseParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                result.id = decoder0.readBytes(8, org.chromium.mojo.bindings.BindingsHelper.NOTHING_NULLABLE, 16);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(id, 8, org.chromium.mojo.bindings.BindingsHelper.NOTHING_NULLABLE, 16);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetIdResponseParams other = (UpdateGetIdResponseParams) object;
+            if (!java.util.Arrays.equals(this.id, other.id))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + java.util.Arrays.hashCode(id);
+            return result;
+        }
+    }
+
+    static class UpdateGetIdResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Update.GetIdResponse mCallback;
+
+        UpdateGetIdResponseParamsForwardToCallback(Update.GetIdResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(GET_ID_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                UpdateGetIdResponseParams response = UpdateGetIdResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.id);
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class UpdateGetIdResponseParamsProxyToResponder implements Update.GetIdResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        UpdateGetIdResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call(byte[] id) {
+            UpdateGetIdResponseParams _response = new UpdateGetIdResponseParams();
+            _response.id = id;
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ID_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+    static final class UpdateGetInterfaceNameParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 8;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(8, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        private UpdateGetInterfaceNameParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetInterfaceNameParams() {
+            this(0);
+        }
+    
+        public static UpdateGetInterfaceNameParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetInterfaceNameParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetInterfaceNameParams result = new UpdateGetInterfaceNameParams(mainDataHeader.elementsOrVersion);
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            return result;
+        }
+    }
+
+    static final class UpdateGetInterfaceNameResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public String interfaceName;
+    
+        private UpdateGetInterfaceNameResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetInterfaceNameResponseParams() {
+            this(0);
+        }
+    
+        public static UpdateGetInterfaceNameResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetInterfaceNameResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetInterfaceNameResponseParams result = new UpdateGetInterfaceNameResponseParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                result.interfaceName = decoder0.readString(8, false);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(interfaceName, 8, false);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetInterfaceNameResponseParams other = (UpdateGetInterfaceNameResponseParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.interfaceName, other.interfaceName))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(interfaceName);
+            return result;
+        }
+    }
+
+    static class UpdateGetInterfaceNameResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Update.GetInterfaceNameResponse mCallback;
+
+        UpdateGetInterfaceNameResponseParamsForwardToCallback(Update.GetInterfaceNameResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(GET_INTERFACE_NAME_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                UpdateGetInterfaceNameResponseParams response = UpdateGetInterfaceNameResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.interfaceName);
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class UpdateGetInterfaceNameResponseParamsProxyToResponder implements Update.GetInterfaceNameResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        UpdateGetInterfaceNameResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call(String interfaceName) {
+            UpdateGetInterfaceNameResponseParams _response = new UpdateGetInterfaceNameResponseParams();
+            _response.interfaceName = interfaceName;
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_INTERFACE_NAME_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+    static final class UpdateGetAddressesParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 8;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(8, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        private UpdateGetAddressesParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetAddressesParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAddressesParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAddressesParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAddressesParams result = new UpdateGetAddressesParams(mainDataHeader.elementsOrVersion);
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            return result;
+        }
+    }
+
+    static final class UpdateGetAddressesResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public String[] addresses;
+    
+        private UpdateGetAddressesResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetAddressesResponseParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAddressesResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAddressesResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAddressesResponseParams result = new UpdateGetAddressesResponseParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(8, false);
+                {
+                    org.chromium.mojo.bindings.DataHeader si1 = decoder1.readDataHeaderForPointerArray(org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
+                    result.addresses = new String[si1.elementsOrVersion];
+                    for (int i1 = 0; i1 < si1.elementsOrVersion; ++i1) {
+                        result.addresses[i1] = decoder1.readString(org.chromium.mojo.bindings.DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i1, false);
+                    }
+                }
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            if (addresses == null) {
+                encoder0.encodeNullPointer(8, false);
+            } else {
+                org.chromium.mojo.bindings.Encoder encoder1 = encoder0.encodePointerArray(addresses.length, 8, org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
+                for (int i0 = 0; i0 < addresses.length; ++i0) {
+                    encoder1.encode(addresses[i0], org.chromium.mojo.bindings.DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i0, false);
+                }
+            }
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetAddressesResponseParams other = (UpdateGetAddressesResponseParams) object;
+            if (!java.util.Arrays.deepEquals(this.addresses, other.addresses))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + java.util.Arrays.deepHashCode(addresses);
+            return result;
+        }
+    }
+
+    static class UpdateGetAddressesResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Update.GetAddressesResponse mCallback;
+
+        UpdateGetAddressesResponseParamsForwardToCallback(Update.GetAddressesResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(GET_ADDRESSES_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                UpdateGetAddressesResponseParams response = UpdateGetAddressesResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.addresses);
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class UpdateGetAddressesResponseParamsProxyToResponder implements Update.GetAddressesResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        UpdateGetAddressesResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call(String[] addresses) {
+            UpdateGetAddressesResponseParams _response = new UpdateGetAddressesResponseParams();
+            _response.addresses = addresses;
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ADDRESSES_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+    static final class UpdateGetAttributeParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public String name;
+    
+        private UpdateGetAttributeParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetAttributeParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAttributeParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAttributeParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAttributeParams result = new UpdateGetAttributeParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                result.name = decoder0.readString(8, false);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(name, 8, false);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetAttributeParams other = (UpdateGetAttributeParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.name, other.name))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(name);
+            return result;
+        }
+    }
+
+    static final class UpdateGetAttributeResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public String attribute;
+    
+        private UpdateGetAttributeResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetAttributeResponseParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAttributeResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAttributeResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAttributeResponseParams result = new UpdateGetAttributeResponseParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                result.attribute = decoder0.readString(8, false);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(attribute, 8, false);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetAttributeResponseParams other = (UpdateGetAttributeResponseParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.attribute, other.attribute))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(attribute);
+            return result;
+        }
+    }
+
+    static class UpdateGetAttributeResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Update.GetAttributeResponse mCallback;
+
+        UpdateGetAttributeResponseParamsForwardToCallback(Update.GetAttributeResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(GET_ATTRIBUTE_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                UpdateGetAttributeResponseParams response = UpdateGetAttributeResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.attribute);
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class UpdateGetAttributeResponseParamsProxyToResponder implements Update.GetAttributeResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        UpdateGetAttributeResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call(String attribute) {
+            UpdateGetAttributeResponseParams _response = new UpdateGetAttributeResponseParams();
+            _response.attribute = attribute;
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ATTRIBUTE_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+    static final class UpdateGetAttachmentParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public String name;
+    
+        private UpdateGetAttachmentParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetAttachmentParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAttachmentParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAttachmentParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAttachmentParams result = new UpdateGetAttachmentParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                result.name = decoder0.readString(8, false);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(name, 8, false);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetAttachmentParams other = (UpdateGetAttachmentParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.name, other.name))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(name);
+            return result;
+        }
+    }
+
+    static final class UpdateGetAttachmentResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public org.chromium.mojo.system.DataPipe.ConsumerHandle data;
+    
+        private UpdateGetAttachmentResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+            data = org.chromium.mojo.system.InvalidHandle.INSTANCE;
+        }
+    
+        public UpdateGetAttachmentResponseParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAttachmentResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAttachmentResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAttachmentResponseParams result = new UpdateGetAttachmentResponseParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                result.data = decoder0.readConsumerHandle(8, false);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(data, 8, false);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetAttachmentResponseParams other = (UpdateGetAttachmentResponseParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.data, other.data))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(data);
+            return result;
+        }
+    }
+
+    static class UpdateGetAttachmentResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Update.GetAttachmentResponse mCallback;
+
+        UpdateGetAttachmentResponseParamsForwardToCallback(Update.GetAttachmentResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(GET_ATTACHMENT_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                UpdateGetAttachmentResponseParams response = UpdateGetAttachmentResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.data);
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class UpdateGetAttachmentResponseParamsProxyToResponder implements Update.GetAttachmentResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        UpdateGetAttachmentResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call(org.chromium.mojo.system.DataPipe.ConsumerHandle data) {
+            UpdateGetAttachmentResponseParams _response = new UpdateGetAttachmentResponseParams();
+            _response.data = data;
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ATTACHMENT_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+    static final class UpdateGetAdvertisementParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 8;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(8, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        private UpdateGetAdvertisementParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetAdvertisementParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAdvertisementParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAdvertisementParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAdvertisementParams result = new UpdateGetAdvertisementParams(mainDataHeader.elementsOrVersion);
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            return result;
+        }
+    }
+
+    static final class UpdateGetAdvertisementResponseParams extends org.chromium.mojo.bindings.Struct {
+    
+        private static final int STRUCT_SIZE = 16;
+        private static final org.chromium.mojo.bindings.DataHeader[] VERSION_ARRAY = new org.chromium.mojo.bindings.DataHeader[] {new org.chromium.mojo.bindings.DataHeader(16, 0)};
+        private static final org.chromium.mojo.bindings.DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[0];
+    
+        public Advertisement ad;
+    
+        private UpdateGetAdvertisementResponseParams(int version) {
+            super(STRUCT_SIZE, version);
+        }
+    
+        public UpdateGetAdvertisementResponseParams() {
+            this(0);
+        }
+    
+        public static UpdateGetAdvertisementResponseParams deserialize(org.chromium.mojo.bindings.Message message) {
+            return decode(new org.chromium.mojo.bindings.Decoder(message));
+        }
+    
+        @SuppressWarnings("unchecked")
+        public static UpdateGetAdvertisementResponseParams decode(org.chromium.mojo.bindings.Decoder decoder0) {
+            if (decoder0 == null) {
+                return null;
+            }
+            org.chromium.mojo.bindings.DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
+            UpdateGetAdvertisementResponseParams result = new UpdateGetAdvertisementResponseParams(mainDataHeader.elementsOrVersion);
+            if (mainDataHeader.elementsOrVersion >= 0) {
+                org.chromium.mojo.bindings.Decoder decoder1 = decoder0.readPointer(8, false);
+                result.ad = Advertisement.decode(decoder1);
+            }
+            return result;
+        }
+    
+        @SuppressWarnings("unchecked")
+        @Override
+        protected final void encode(org.chromium.mojo.bindings.Encoder encoder) {
+            org.chromium.mojo.bindings.Encoder encoder0 = encoder.getEncoderAtDataOffset(DEFAULT_STRUCT_INFO);
+            encoder0.encode(ad, 8, false);
+        }
+    
+        /**
+         * @see Object#equals(Object)
+         */
+        @Override
+        public boolean equals(Object object) {
+            if (object == this)
+                return true;
+            if (object == null)
+                return false;
+            if (getClass() != object.getClass())
+                return false;
+            UpdateGetAdvertisementResponseParams other = (UpdateGetAdvertisementResponseParams) object;
+            if (!org.chromium.mojo.bindings.BindingsHelper.equals(this.ad, other.ad))
+                return false;
+            return true;
+        }
+    
+        /**
+         * @see Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + getClass().hashCode();
+            result = prime * result + org.chromium.mojo.bindings.BindingsHelper.hashCode(ad);
+            return result;
+        }
+    }
+
+    static class UpdateGetAdvertisementResponseParamsForwardToCallback extends org.chromium.mojo.bindings.SideEffectFreeCloseable
+            implements org.chromium.mojo.bindings.MessageReceiver {
+        private final Update.GetAdvertisementResponse mCallback;
+
+        UpdateGetAdvertisementResponseParamsForwardToCallback(Update.GetAdvertisementResponse callback) {
+            this.mCallback = callback;
+        }
+
+        @Override
+        public boolean accept(org.chromium.mojo.bindings.Message message) {
+            try {
+                org.chromium.mojo.bindings.ServiceMessage messageWithHeader =
+                        message.asServiceMessage();
+                org.chromium.mojo.bindings.MessageHeader header = messageWithHeader.getHeader();
+                if (!header.validateHeader(GET_ADVERTISEMENT_ORDINAL,
+                                           org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
+                    return false;
+                }
+                UpdateGetAdvertisementResponseParams response = UpdateGetAdvertisementResponseParams.deserialize(messageWithHeader.getPayload());
+                mCallback.call(response.ad);
+                return true;
+            } catch (org.chromium.mojo.bindings.DeserializationException e) {
+                return false;
+            }
+        }
+    }
+
+    static class UpdateGetAdvertisementResponseParamsProxyToResponder implements Update.GetAdvertisementResponse {
+
+        private final org.chromium.mojo.system.Core mCore;
+        private final org.chromium.mojo.bindings.MessageReceiver mMessageReceiver;
+        private final long mRequestId;
+
+        UpdateGetAdvertisementResponseParamsProxyToResponder(
+                org.chromium.mojo.system.Core core,
+                org.chromium.mojo.bindings.MessageReceiver messageReceiver,
+                long requestId) {
+            mCore = core;
+            mMessageReceiver = messageReceiver;
+            mRequestId = requestId;
+        }
+
+        @Override
+        public void call(Advertisement ad) {
+            UpdateGetAdvertisementResponseParams _response = new UpdateGetAdvertisementResponseParams();
+            _response.ad = ad;
+            org.chromium.mojo.bindings.ServiceMessage _message =
+                    _response.serializeWithHeader(
+                            mCore,
+                            new org.chromium.mojo.bindings.MessageHeader(
+                                    GET_ADVERTISEMENT_ORDINAL,
+                                    org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG,
+                                    mRequestId));
+            mMessageReceiver.accept(_message);
+        }
+    }
+
+}
+
diff --git a/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart b/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart
index 55902c3..20eb267 100644
--- a/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart
+++ b/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart
@@ -11,76 +11,22 @@
 import 'package:mojo/mojo/bindings/types/mojom_types.mojom.dart' as mojom_types;
 import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' as service_describer;
 
-class UpdateType extends bindings.MojoEnum {
-  static const UpdateType found = const UpdateType._(1);
-  static const UpdateType lost = const UpdateType._(2);
-
-  const UpdateType._(int v) : super(v);
-
-  static const Map<String, UpdateType> valuesMap = const {
-    "found": found,
-    "lost": lost,
-  };
-  static const List<UpdateType> values = const [
-    found,
-    lost,
-  ];
-
-  static UpdateType valueOf(String name) => valuesMap[name];
-
-  factory UpdateType(int v) {
-    switch (v) {
-      case 1:
-        return found;
-      case 2:
-        return lost;
-      default:
-        return null;
-    }
-  }
-
-  static UpdateType decode(bindings.Decoder decoder0, int offset) {
-    int v = decoder0.decodeUint32(offset);
-    UpdateType result = new UpdateType(v);
-    if (result == null) {
-      throw new bindings.MojoCodecError(
-          'Bad value $v for enum UpdateType.');
-    }
-    return result;
-  }
-
-  String toString() {
-    switch(this) {
-      case found:
-        return 'UpdateType.found';
-      case lost:
-        return 'UpdateType.lost';
-      default:
-        return null;
-    }
-  }
-
-  int toJson() => mojoEnumValue;
-}
 
 
-
-
-
-class Service extends bindings.Struct {
+class Advertisement extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(56, 0)
+    const bindings.StructDataHeader(48, 0)
   ];
-  String instanceId = null;
-  String instanceName = null;
+  static const int idLen = 16;
+  List<int> id = null;
   String interfaceName = null;
-  Map<String, String> attrs = null;
-  List<String> addrs = null;
+  List<String> addresses = null;
+  Map<String, String> attributes = null;
   Map<String, List<int>> attachments = null;
 
-  Service() : super(kVersions.last.size);
+  Advertisement() : super(kVersions.last.size);
 
-  static Service deserialize(bindings.Message message) {
+  static Advertisement deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -89,11 +35,11 @@
     return result;
   }
 
-  static Service decode(bindings.Decoder decoder0) {
+  static Advertisement decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    Service result = new Service();
+    Advertisement result = new Advertisement();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -115,21 +61,29 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      result.instanceId = decoder0.decodeString(8, true);
+      result.id = decoder0.decodeUint8Array(8, bindings.kArrayNullable, 16);
     }
     if (mainDataHeader.version >= 0) {
       
-      result.instanceName = decoder0.decodeString(16, true);
+      result.interfaceName = decoder0.decodeString(16, false);
     }
     if (mainDataHeader.version >= 0) {
       
-      result.interfaceName = decoder0.decodeString(24, false);
+      var decoder1 = decoder0.decodePointer(24, false);
+      {
+        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
+        result.addresses = new List<String>(si1.numElements);
+        for (int i1 = 0; i1 < si1.numElements; ++i1) {
+          
+          result.addresses[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
+        }
+      }
     }
     if (mainDataHeader.version >= 0) {
       
       var decoder1 = decoder0.decodePointer(32, true);
       if (decoder1 == null) {
-        result.attrs = null;
+        result.attributes = null;
       } else {
         decoder1.decodeDataHeaderForMap();
         List<String> keys0;
@@ -158,25 +112,13 @@
             }
           }
         }
-        result.attrs = new Map<String, String>.fromIterables(
+        result.attributes = new Map<String, String>.fromIterables(
             keys0, values0);
       }
     }
     if (mainDataHeader.version >= 0) {
       
-      var decoder1 = decoder0.decodePointer(40, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.addrs = new List<String>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          result.addrs[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(48, true);
+      var decoder1 = decoder0.decodePointer(40, true);
       if (decoder1 == null) {
         result.attachments = null;
       } else {
@@ -217,19 +159,27 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     
-    encoder0.encodeString(instanceId, 8, true);
+    encoder0.encodeUint8Array(id, 8, bindings.kArrayNullable, 16);
     
-    encoder0.encodeString(instanceName, 16, true);
+    encoder0.encodeString(interfaceName, 16, false);
     
-    encoder0.encodeString(interfaceName, 24, false);
+    if (addresses == null) {
+      encoder0.encodeNullPointer(24, false);
+    } else {
+      var encoder1 = encoder0.encodePointerArray(addresses.length, 24, bindings.kUnspecifiedArrayLength);
+      for (int i0 = 0; i0 < addresses.length; ++i0) {
+        
+        encoder1.encodeString(addresses[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
+      }
+    }
     
-    if (attrs == null) {
+    if (attributes == null) {
       encoder0.encodeNullPointer(32, true);
     } else {
       var encoder1 = encoder0.encoderForMap(32);
-      int size0 = attrs.length;
-      var keys0 = attrs.keys.toList();
-      var values0 = attrs.values.toList();
+      int size0 = attributes.length;
+      var keys0 = attributes.keys.toList();
+      var values0 = attributes.values.toList();
       
       {
         var encoder2 = encoder1.encodePointerArray(keys0.length, bindings.ArrayDataHeader.kHeaderSize, bindings.kUnspecifiedArrayLength);
@@ -248,20 +198,10 @@
       }
     }
     
-    if (addrs == null) {
-      encoder0.encodeNullPointer(40, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(addrs.length, 40, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < addrs.length; ++i0) {
-        
-        encoder1.encodeString(addrs[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-    
     if (attachments == null) {
-      encoder0.encodeNullPointer(48, true);
+      encoder0.encodeNullPointer(40, true);
     } else {
-      var encoder1 = encoder0.encoderForMap(48);
+      var encoder1 = encoder0.encoderForMap(40);
       int size0 = attachments.length;
       var keys0 = attachments.keys.toList();
       var values0 = attachments.values.toList();
@@ -285,22 +225,20 @@
   }
 
   String toString() {
-    return "Service("
-           "instanceId: $instanceId" ", "
-           "instanceName: $instanceName" ", "
+    return "Advertisement("
+           "id: $id" ", "
            "interfaceName: $interfaceName" ", "
-           "attrs: $attrs" ", "
-           "addrs: $addrs" ", "
+           "addresses: $addresses" ", "
+           "attributes: $attributes" ", "
            "attachments: $attachments" ")";
   }
 
   Map toJson() {
     Map map = new Map();
-    map["instanceId"] = instanceId;
-    map["instanceName"] = instanceName;
+    map["id"] = id;
     map["interfaceName"] = interfaceName;
-    map["attrs"] = attrs;
-    map["addrs"] = addrs;
+    map["addresses"] = addresses;
+    map["attributes"] = attributes;
     map["attachments"] = attachments;
     return map;
   }
@@ -309,95 +247,12 @@
 
 
 
-class ScanUpdate extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Service service = null;
-  UpdateType updateType = null;
-
-  ScanUpdate() : super(kVersions.last.size);
-
-  static ScanUpdate deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    if (decoder.excessHandles != null) {
-      decoder.excessHandles.forEach((h) => h.close());
-    }
-    return result;
-  }
-
-  static ScanUpdate decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    ScanUpdate result = new ScanUpdate();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.service = Service.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-        result.updateType = UpdateType.decode(decoder0, 16);
-        if (result.updateType == null) {
-          throw new bindings.MojoCodecError(
-            'Trying to decode null union for non-nullable UpdateType.');
-        }
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(service, 8, false);
-    
-    encoder0.encodeEnum(updateType, 16);
-  }
-
-  String toString() {
-    return "ScanUpdate("
-           "service: $service" ", "
-           "updateType: $updateType" ")";
-  }
-
-  Map toJson() {
-    Map map = new Map();
-    map["service"] = service;
-    map["updateType"] = updateType;
-    return map;
-  }
-}
-
-
-
-
 class Error extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
     const bindings.StructDataHeader(32, 0)
   ];
   String id = null;
-  int action = 0;
+  int actionCode = 0;
   String msg = null;
 
   Error() : super(kVersions.last.size);
@@ -441,7 +296,7 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      result.action = decoder0.decodeInt32(16);
+      result.actionCode = decoder0.decodeUint32(16);
     }
     if (mainDataHeader.version >= 0) {
       
@@ -455,7 +310,7 @@
     
     encoder0.encodeString(id, 8, false);
     
-    encoder0.encodeInt32(action, 16);
+    encoder0.encodeUint32(actionCode, 16);
     
     encoder0.encodeString(msg, 24, false);
   }
@@ -463,14 +318,14 @@
   String toString() {
     return "Error("
            "id: $id" ", "
-           "action: $action" ", "
+           "actionCode: $actionCode" ", "
            "msg: $msg" ")";
   }
 
   Map toJson() {
     Map map = new Map();
     map["id"] = id;
-    map["action"] = action;
+    map["actionCode"] = actionCode;
     map["msg"] = msg;
     return map;
   }
@@ -479,16 +334,16 @@
 
 
 
-class _DiscoveryStartAdvertisingParams extends bindings.Struct {
+class _DiscoveryAdvertiseParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
     const bindings.StructDataHeader(24, 0)
   ];
-  Service service = null;
+  Advertisement ad = null;
   List<String> visibility = null;
 
-  _DiscoveryStartAdvertisingParams() : super(kVersions.last.size);
+  _DiscoveryAdvertiseParams() : super(kVersions.last.size);
 
-  static _DiscoveryStartAdvertisingParams deserialize(bindings.Message message) {
+  static _DiscoveryAdvertiseParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -497,11 +352,11 @@
     return result;
   }
 
-  static _DiscoveryStartAdvertisingParams decode(bindings.Decoder decoder0) {
+  static _DiscoveryAdvertiseParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    _DiscoveryStartAdvertisingParams result = new _DiscoveryStartAdvertisingParams();
+    _DiscoveryAdvertiseParams result = new _DiscoveryAdvertiseParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -524,7 +379,7 @@
     if (mainDataHeader.version >= 0) {
       
       var decoder1 = decoder0.decodePointer(8, false);
-      result.service = Service.decode(decoder1);
+      result.ad = Advertisement.decode(decoder1);
     }
     if (mainDataHeader.version >= 0) {
       
@@ -546,7 +401,7 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     
-    encoder0.encodeStruct(service, 8, false);
+    encoder0.encodeStruct(ad, 8, false);
     
     if (visibility == null) {
       encoder0.encodeNullPointer(16, true);
@@ -560,14 +415,14 @@
   }
 
   String toString() {
-    return "_DiscoveryStartAdvertisingParams("
-           "service: $service" ", "
+    return "_DiscoveryAdvertiseParams("
+           "ad: $ad" ", "
            "visibility: $visibility" ")";
   }
 
   Map toJson() {
     Map map = new Map();
-    map["service"] = service;
+    map["ad"] = ad;
     map["visibility"] = visibility;
     return map;
   }
@@ -576,16 +431,17 @@
 
 
 
-class DiscoveryStartAdvertisingResponseParams extends bindings.Struct {
+class DiscoveryAdvertiseResponseParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
+    const bindings.StructDataHeader(32, 0)
   ];
-  String instanceId = null;
+  List<int> instanceId = null;
+  Object closer = null;
   Error err = null;
 
-  DiscoveryStartAdvertisingResponseParams() : super(kVersions.last.size);
+  DiscoveryAdvertiseResponseParams() : super(kVersions.last.size);
 
-  static DiscoveryStartAdvertisingResponseParams deserialize(bindings.Message message) {
+  static DiscoveryAdvertiseResponseParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -594,11 +450,11 @@
     return result;
   }
 
-  static DiscoveryStartAdvertisingResponseParams decode(bindings.Decoder decoder0) {
+  static DiscoveryAdvertiseResponseParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    DiscoveryStartAdvertisingResponseParams result = new DiscoveryStartAdvertisingResponseParams();
+    DiscoveryAdvertiseResponseParams result = new DiscoveryAdvertiseResponseParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -620,11 +476,15 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      result.instanceId = decoder0.decodeString(8, false);
+      result.instanceId = decoder0.decodeUint8Array(8, bindings.kArrayNullable, 16);
     }
     if (mainDataHeader.version >= 0) {
       
-      var decoder1 = decoder0.decodePointer(16, true);
+      result.closer = decoder0.decodeServiceInterface(16, true, CloserProxy.newFromEndpoint);
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      var decoder1 = decoder0.decodePointer(24, true);
       result.err = Error.decode(decoder1);
     }
     return result;
@@ -633,177 +493,39 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     
-    encoder0.encodeString(instanceId, 8, false);
+    encoder0.encodeUint8Array(instanceId, 8, bindings.kArrayNullable, 16);
     
-    encoder0.encodeStruct(err, 16, true);
+    encoder0.encodeInterface(closer, 16, true);
+    
+    encoder0.encodeStruct(err, 24, true);
   }
 
   String toString() {
-    return "DiscoveryStartAdvertisingResponseParams("
+    return "DiscoveryAdvertiseResponseParams("
            "instanceId: $instanceId" ", "
+           "closer: $closer" ", "
            "err: $err" ")";
   }
 
   Map toJson() {
-    Map map = new Map();
-    map["instanceId"] = instanceId;
-    map["err"] = err;
-    return map;
+    throw new bindings.MojoCodecError(
+        'Object containing handles cannot be encoded to JSON.');
   }
 }
 
 
 
 
-class _DiscoveryStopAdvertisingParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String instanceId = null;
-
-  _DiscoveryStopAdvertisingParams() : super(kVersions.last.size);
-
-  static _DiscoveryStopAdvertisingParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    if (decoder.excessHandles != null) {
-      decoder.excessHandles.forEach((h) => h.close());
-    }
-    return result;
-  }
-
-  static _DiscoveryStopAdvertisingParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    _DiscoveryStopAdvertisingParams result = new _DiscoveryStopAdvertisingParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.instanceId = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(instanceId, 8, false);
-  }
-
-  String toString() {
-    return "_DiscoveryStopAdvertisingParams("
-           "instanceId: $instanceId" ")";
-  }
-
-  Map toJson() {
-    Map map = new Map();
-    map["instanceId"] = instanceId;
-    return map;
-  }
-}
-
-
-
-
-class DiscoveryStopAdvertisingResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  DiscoveryStopAdvertisingResponseParams() : super(kVersions.last.size);
-
-  static DiscoveryStopAdvertisingResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    if (decoder.excessHandles != null) {
-      decoder.excessHandles.forEach((h) => h.close());
-    }
-    return result;
-  }
-
-  static DiscoveryStopAdvertisingResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    DiscoveryStopAdvertisingResponseParams result = new DiscoveryStopAdvertisingResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, true);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, true);
-  }
-
-  String toString() {
-    return "DiscoveryStopAdvertisingResponseParams("
-           "err: $err" ")";
-  }
-
-  Map toJson() {
-    Map map = new Map();
-    map["err"] = err;
-    return map;
-  }
-}
-
-
-
-
-class _DiscoveryStartScanParams extends bindings.Struct {
+class _DiscoveryScanParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
     const bindings.StructDataHeader(24, 0)
   ];
   String query = null;
   Object handler = null;
 
-  _DiscoveryStartScanParams() : super(kVersions.last.size);
+  _DiscoveryScanParams() : super(kVersions.last.size);
 
-  static _DiscoveryStartScanParams deserialize(bindings.Message message) {
+  static _DiscoveryScanParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -812,11 +534,11 @@
     return result;
   }
 
-  static _DiscoveryStartScanParams decode(bindings.Decoder decoder0) {
+  static _DiscoveryScanParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    _DiscoveryStartScanParams result = new _DiscoveryStartScanParams();
+    _DiscoveryScanParams result = new _DiscoveryScanParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -856,7 +578,7 @@
   }
 
   String toString() {
-    return "_DiscoveryStartScanParams("
+    return "_DiscoveryScanParams("
            "query: $query" ", "
            "handler: $handler" ")";
   }
@@ -870,16 +592,16 @@
 
 
 
-class DiscoveryStartScanResponseParams extends bindings.Struct {
+class DiscoveryScanResponseParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
     const bindings.StructDataHeader(24, 0)
   ];
-  int scanId = 0;
+  Object closer = null;
   Error err = null;
 
-  DiscoveryStartScanResponseParams() : super(kVersions.last.size);
+  DiscoveryScanResponseParams() : super(kVersions.last.size);
 
-  static DiscoveryStartScanResponseParams deserialize(bindings.Message message) {
+  static DiscoveryScanResponseParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -888,11 +610,11 @@
     return result;
   }
 
-  static DiscoveryStartScanResponseParams decode(bindings.Decoder decoder0) {
+  static DiscoveryScanResponseParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    DiscoveryStartScanResponseParams result = new DiscoveryStartScanResponseParams();
+    DiscoveryScanResponseParams result = new DiscoveryScanResponseParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -914,7 +636,7 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      result.scanId = decoder0.decodeUint32(8);
+      result.closer = decoder0.decodeServiceInterface(8, true, CloserProxy.newFromEndpoint);
     }
     if (mainDataHeader.version >= 0) {
       
@@ -927,37 +649,34 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     
-    encoder0.encodeUint32(scanId, 8);
+    encoder0.encodeInterface(closer, 8, true);
     
     encoder0.encodeStruct(err, 16, true);
   }
 
   String toString() {
-    return "DiscoveryStartScanResponseParams("
-           "scanId: $scanId" ", "
+    return "DiscoveryScanResponseParams("
+           "closer: $closer" ", "
            "err: $err" ")";
   }
 
   Map toJson() {
-    Map map = new Map();
-    map["scanId"] = scanId;
-    map["err"] = err;
-    return map;
+    throw new bindings.MojoCodecError(
+        'Object containing handles cannot be encoded to JSON.');
   }
 }
 
 
 
 
-class _DiscoveryStopScanParams extends bindings.Struct {
+class _CloserCloseParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
+    const bindings.StructDataHeader(8, 0)
   ];
-  int scanId = 0;
 
-  _DiscoveryStopScanParams() : super(kVersions.last.size);
+  _CloserCloseParams() : super(kVersions.last.size);
 
-  static _DiscoveryStopScanParams deserialize(bindings.Message message) {
+  static _CloserCloseParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -966,11 +685,132 @@
     return result;
   }
 
-  static _DiscoveryStopScanParams decode(bindings.Decoder decoder0) {
+  static _CloserCloseParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    _DiscoveryStopScanParams result = new _DiscoveryStopScanParams();
+    _CloserCloseParams result = new _CloserCloseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "_CloserCloseParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+
+
+class CloserCloseResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  CloserCloseResponseParams() : super(kVersions.last.size);
+
+  static CloserCloseResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static CloserCloseResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    CloserCloseResponseParams result = new CloserCloseResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "CloserCloseResponseParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+
+
+class _ScanHandlerOnUpdateParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  Object update = null;
+
+  _ScanHandlerOnUpdateParams() : super(kVersions.last.size);
+
+  static _ScanHandlerOnUpdateParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static _ScanHandlerOnUpdateParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    _ScanHandlerOnUpdateParams result = new _ScanHandlerOnUpdateParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -992,7 +832,7 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      result.scanId = decoder0.decodeUint32(8);
+      result.update = decoder0.decodeServiceInterface(8, false, UpdateProxy.newFromEndpoint);
     }
     return result;
   }
@@ -1000,33 +840,31 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     
-    encoder0.encodeUint32(scanId, 8);
+    encoder0.encodeInterface(update, 8, false);
   }
 
   String toString() {
-    return "_DiscoveryStopScanParams("
-           "scanId: $scanId" ")";
+    return "_ScanHandlerOnUpdateParams("
+           "update: $update" ")";
   }
 
   Map toJson() {
-    Map map = new Map();
-    map["scanId"] = scanId;
-    return map;
+    throw new bindings.MojoCodecError(
+        'Object containing handles cannot be encoded to JSON.');
   }
 }
 
 
 
 
-class DiscoveryStopScanResponseParams extends bindings.Struct {
+class _UpdateIsLostParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
+    const bindings.StructDataHeader(8, 0)
   ];
-  Error err = null;
 
-  DiscoveryStopScanResponseParams() : super(kVersions.last.size);
+  _UpdateIsLostParams() : super(kVersions.last.size);
 
-  static DiscoveryStopScanResponseParams deserialize(bindings.Message message) {
+  static _UpdateIsLostParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -1035,11 +873,72 @@
     return result;
   }
 
-  static DiscoveryStopScanResponseParams decode(bindings.Decoder decoder0) {
+  static _UpdateIsLostParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    DiscoveryStopScanResponseParams result = new DiscoveryStopScanResponseParams();
+    _UpdateIsLostParams result = new _UpdateIsLostParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "_UpdateIsLostParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+
+
+class UpdateIsLostResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  bool lost = false;
+
+  UpdateIsLostResponseParams() : super(kVersions.last.size);
+
+  static UpdateIsLostResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UpdateIsLostResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UpdateIsLostResponseParams result = new UpdateIsLostResponseParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -1061,8 +960,7 @@
     }
     if (mainDataHeader.version >= 0) {
       
-      var decoder1 = decoder0.decodePointer(8, true);
-      result.err = Error.decode(decoder1);
+      result.lost = decoder0.decodeBool(8, 0);
     }
     return result;
   }
@@ -1070,17 +968,17 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     
-    encoder0.encodeStruct(err, 8, true);
+    encoder0.encodeBool(lost, 8, 0);
   }
 
   String toString() {
-    return "DiscoveryStopScanResponseParams("
-           "err: $err" ")";
+    return "UpdateIsLostResponseParams("
+           "lost: $lost" ")";
   }
 
   Map toJson() {
     Map map = new Map();
-    map["err"] = err;
+    map["lost"] = lost;
     return map;
   }
 }
@@ -1088,15 +986,14 @@
 
 
 
-class _ScanHandlerUpdateParams extends bindings.Struct {
+class _UpdateGetIdParams extends bindings.Struct {
   static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
+    const bindings.StructDataHeader(8, 0)
   ];
-  ScanUpdate update = null;
 
-  _ScanHandlerUpdateParams() : super(kVersions.last.size);
+  _UpdateGetIdParams() : super(kVersions.last.size);
 
-  static _ScanHandlerUpdateParams deserialize(bindings.Message message) {
+  static _UpdateGetIdParams deserialize(bindings.Message message) {
     var decoder = new bindings.Decoder(message);
     var result = decode(decoder);
     if (decoder.excessHandles != null) {
@@ -1105,11 +1002,330 @@
     return result;
   }
 
-  static _ScanHandlerUpdateParams decode(bindings.Decoder decoder0) {
+  static _UpdateGetIdParams decode(bindings.Decoder decoder0) {
     if (decoder0 == null) {
       return null;
     }
-    _ScanHandlerUpdateParams result = new _ScanHandlerUpdateParams();
+    _UpdateGetIdParams result = new _UpdateGetIdParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "_UpdateGetIdParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+
+
+class UpdateGetIdResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  List<int> id = null;
+
+  UpdateGetIdResponseParams() : super(kVersions.last.size);
+
+  static UpdateGetIdResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UpdateGetIdResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UpdateGetIdResponseParams result = new UpdateGetIdResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.id = decoder0.decodeUint8Array(8, bindings.kNothingNullable, 16);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeUint8Array(id, 8, bindings.kNothingNullable, 16);
+  }
+
+  String toString() {
+    return "UpdateGetIdResponseParams("
+           "id: $id" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["id"] = id;
+    return map;
+  }
+}
+
+
+
+
+class _UpdateGetInterfaceNameParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  _UpdateGetInterfaceNameParams() : super(kVersions.last.size);
+
+  static _UpdateGetInterfaceNameParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static _UpdateGetInterfaceNameParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    _UpdateGetInterfaceNameParams result = new _UpdateGetInterfaceNameParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "_UpdateGetInterfaceNameParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+
+
+class UpdateGetInterfaceNameResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  String interfaceName = null;
+
+  UpdateGetInterfaceNameResponseParams() : super(kVersions.last.size);
+
+  static UpdateGetInterfaceNameResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UpdateGetInterfaceNameResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UpdateGetInterfaceNameResponseParams result = new UpdateGetInterfaceNameResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.interfaceName = decoder0.decodeString(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(interfaceName, 8, false);
+  }
+
+  String toString() {
+    return "UpdateGetInterfaceNameResponseParams("
+           "interfaceName: $interfaceName" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["interfaceName"] = interfaceName;
+    return map;
+  }
+}
+
+
+
+
+class _UpdateGetAddressesParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  _UpdateGetAddressesParams() : super(kVersions.last.size);
+
+  static _UpdateGetAddressesParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static _UpdateGetAddressesParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    _UpdateGetAddressesParams result = new _UpdateGetAddressesParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "_UpdateGetAddressesParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+
+
+class UpdateGetAddressesResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  List<String> addresses = null;
+
+  UpdateGetAddressesResponseParams() : super(kVersions.last.size);
+
+  static UpdateGetAddressesResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UpdateGetAddressesResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UpdateGetAddressesResponseParams result = new UpdateGetAddressesResponseParams();
 
     var mainDataHeader = decoder0.decodeStructDataHeader();
     if (mainDataHeader.version <= kVersions.last.version) {
@@ -1132,7 +1348,14 @@
     if (mainDataHeader.version >= 0) {
       
       var decoder1 = decoder0.decodePointer(8, false);
-      result.update = ScanUpdate.decode(decoder1);
+      {
+        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
+        result.addresses = new List<String>(si1.numElements);
+        for (int i1 = 0; i1 < si1.numElements; ++i1) {
+          
+          result.addresses[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
+        }
+      }
     }
     return result;
   }
@@ -1140,17 +1363,25 @@
   void encode(bindings.Encoder encoder) {
     var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
     
-    encoder0.encodeStruct(update, 8, false);
+    if (addresses == null) {
+      encoder0.encodeNullPointer(8, false);
+    } else {
+      var encoder1 = encoder0.encodePointerArray(addresses.length, 8, bindings.kUnspecifiedArrayLength);
+      for (int i0 = 0; i0 < addresses.length; ++i0) {
+        
+        encoder1.encodeString(addresses[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
+      }
+    }
   }
 
   String toString() {
-    return "_ScanHandlerUpdateParams("
-           "update: $update" ")";
+    return "UpdateGetAddressesResponseParams("
+           "addresses: $addresses" ")";
   }
 
   Map toJson() {
     Map map = new Map();
-    map["update"] = update;
+    map["addresses"] = addresses;
     return map;
   }
 }
@@ -1158,10 +1389,413 @@
 
 
 
-const int _Discovery_startAdvertisingName = 0;
-const int _Discovery_stopAdvertisingName = 1;
-const int _Discovery_startScanName = 2;
-const int _Discovery_stopScanName = 3;
+class _UpdateGetAttributeParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  String name = null;
+
+  _UpdateGetAttributeParams() : super(kVersions.last.size);
+
+  static _UpdateGetAttributeParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static _UpdateGetAttributeParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    _UpdateGetAttributeParams result = new _UpdateGetAttributeParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.name = decoder0.decodeString(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(name, 8, false);
+  }
+
+  String toString() {
+    return "_UpdateGetAttributeParams("
+           "name: $name" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["name"] = name;
+    return map;
+  }
+}
+
+
+
+
+class UpdateGetAttributeResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  String attribute = null;
+
+  UpdateGetAttributeResponseParams() : super(kVersions.last.size);
+
+  static UpdateGetAttributeResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UpdateGetAttributeResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UpdateGetAttributeResponseParams result = new UpdateGetAttributeResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.attribute = decoder0.decodeString(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(attribute, 8, false);
+  }
+
+  String toString() {
+    return "UpdateGetAttributeResponseParams("
+           "attribute: $attribute" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["attribute"] = attribute;
+    return map;
+  }
+}
+
+
+
+
+class _UpdateGetAttachmentParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  String name = null;
+
+  _UpdateGetAttachmentParams() : super(kVersions.last.size);
+
+  static _UpdateGetAttachmentParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static _UpdateGetAttachmentParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    _UpdateGetAttachmentParams result = new _UpdateGetAttachmentParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.name = decoder0.decodeString(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeString(name, 8, false);
+  }
+
+  String toString() {
+    return "_UpdateGetAttachmentParams("
+           "name: $name" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["name"] = name;
+    return map;
+  }
+}
+
+
+
+
+class UpdateGetAttachmentResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  core.MojoDataPipeConsumer data = null;
+
+  UpdateGetAttachmentResponseParams() : super(kVersions.last.size);
+
+  static UpdateGetAttachmentResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UpdateGetAttachmentResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UpdateGetAttachmentResponseParams result = new UpdateGetAttachmentResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      result.data = decoder0.decodeConsumerHandle(8, false);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeConsumerHandle(data, 8, false);
+  }
+
+  String toString() {
+    return "UpdateGetAttachmentResponseParams("
+           "data: $data" ")";
+  }
+
+  Map toJson() {
+    throw new bindings.MojoCodecError(
+        'Object containing handles cannot be encoded to JSON.');
+  }
+}
+
+
+
+
+class _UpdateGetAdvertisementParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(8, 0)
+  ];
+
+  _UpdateGetAdvertisementParams() : super(kVersions.last.size);
+
+  static _UpdateGetAdvertisementParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static _UpdateGetAdvertisementParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    _UpdateGetAdvertisementParams result = new _UpdateGetAdvertisementParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    encoder.getStructEncoderAtOffset(kVersions.last);
+  }
+
+  String toString() {
+    return "_UpdateGetAdvertisementParams("")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    return map;
+  }
+}
+
+
+
+
+class UpdateGetAdvertisementResponseParams extends bindings.Struct {
+  static const List<bindings.StructDataHeader> kVersions = const [
+    const bindings.StructDataHeader(16, 0)
+  ];
+  Advertisement ad = null;
+
+  UpdateGetAdvertisementResponseParams() : super(kVersions.last.size);
+
+  static UpdateGetAdvertisementResponseParams deserialize(bindings.Message message) {
+    var decoder = new bindings.Decoder(message);
+    var result = decode(decoder);
+    if (decoder.excessHandles != null) {
+      decoder.excessHandles.forEach((h) => h.close());
+    }
+    return result;
+  }
+
+  static UpdateGetAdvertisementResponseParams decode(bindings.Decoder decoder0) {
+    if (decoder0 == null) {
+      return null;
+    }
+    UpdateGetAdvertisementResponseParams result = new UpdateGetAdvertisementResponseParams();
+
+    var mainDataHeader = decoder0.decodeStructDataHeader();
+    if (mainDataHeader.version <= kVersions.last.version) {
+      // Scan in reverse order to optimize for more recent versions.
+      for (int i = kVersions.length - 1; i >= 0; --i) {
+        if (mainDataHeader.version >= kVersions[i].version) {
+          if (mainDataHeader.size == kVersions[i].size) {
+            // Found a match.
+            break;
+          }
+          throw new bindings.MojoCodecError(
+              'Header size doesn\'t correspond to known version size.');
+        }
+      }
+    } else if (mainDataHeader.size < kVersions.last.size) {
+      throw new bindings.MojoCodecError(
+        'Message newer than the last known version cannot be shorter than '
+        'required by the last known version.');
+    }
+    if (mainDataHeader.version >= 0) {
+      
+      var decoder1 = decoder0.decodePointer(8, false);
+      result.ad = Advertisement.decode(decoder1);
+    }
+    return result;
+  }
+
+  void encode(bindings.Encoder encoder) {
+    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+    
+    encoder0.encodeStruct(ad, 8, false);
+  }
+
+  String toString() {
+    return "UpdateGetAdvertisementResponseParams("
+           "ad: $ad" ")";
+  }
+
+  Map toJson() {
+    Map map = new Map();
+    map["ad"] = ad;
+    return map;
+  }
+}
+
+
+
+
+const int _Discovery_advertiseName = 0;
+const int _Discovery_scanName = 1;
 
 
 
@@ -1175,10 +1809,8 @@
 
 abstract class Discovery {
   static const String serviceName = "v23::discovery::Discovery";
-  dynamic startAdvertising(Service service,List<String> visibility,[Function responseFactory = null]);
-  dynamic stopAdvertising(String instanceId,[Function responseFactory = null]);
-  dynamic startScan(String query,Object handler,[Function responseFactory = null]);
-  dynamic stopScan(int scanId,[Function responseFactory = null]);
+  dynamic advertise(Advertisement ad,List<String> visibility,[Function responseFactory = null]);
+  dynamic scan(String query,Object handler,[Function responseFactory = null]);
 }
 
 
@@ -1202,8 +1834,8 @@
 
   void handleResponse(bindings.ServiceMessage message) {
     switch (message.header.type) {
-      case _Discovery_startAdvertisingName:
-        var r = DiscoveryStartAdvertisingResponseParams.deserialize(
+      case _Discovery_advertiseName:
+        var r = DiscoveryAdvertiseResponseParams.deserialize(
             message.payload);
         if (!message.header.hasRequestId) {
           proxyError("Expected a message with a valid request Id.");
@@ -1222,48 +1854,8 @@
         }
         c.complete(r);
         break;
-      case _Discovery_stopAdvertisingName:
-        var r = DiscoveryStopAdvertisingResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          proxyError("Expected a message with a valid request Id.");
-          return;
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          proxyError(
-              "Message had unknown request Id: ${message.header.requestId}");
-          return;
-        }
-        completerMap.remove(message.header.requestId);
-        if (c.isCompleted) {
-          proxyError("Response completer already completed");
-          return;
-        }
-        c.complete(r);
-        break;
-      case _Discovery_startScanName:
-        var r = DiscoveryStartScanResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          proxyError("Expected a message with a valid request Id.");
-          return;
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          proxyError(
-              "Message had unknown request Id: ${message.header.requestId}");
-          return;
-        }
-        completerMap.remove(message.header.requestId);
-        if (c.isCompleted) {
-          proxyError("Response completer already completed");
-          return;
-        }
-        c.complete(r);
-        break;
-      case _Discovery_stopScanName:
-        var r = DiscoveryStopScanResponseParams.deserialize(
+      case _Discovery_scanName:
+        var r = DiscoveryScanResponseParams.deserialize(
             message.payload);
         if (!message.header.hasRequestId) {
           proxyError("Expected a message with a valid request Id.");
@@ -1300,41 +1892,23 @@
   _DiscoveryProxyImpl _proxyImpl;
 
   _DiscoveryProxyCalls(this._proxyImpl);
-    dynamic startAdvertising(Service service,List<String> visibility,[Function responseFactory = null]) {
-      var params = new _DiscoveryStartAdvertisingParams();
-      params.service = service;
+    dynamic advertise(Advertisement ad,List<String> visibility,[Function responseFactory = null]) {
+      var params = new _DiscoveryAdvertiseParams();
+      params.ad = ad;
       params.visibility = visibility;
       return _proxyImpl.sendMessageWithRequestId(
           params,
-          _Discovery_startAdvertisingName,
+          _Discovery_advertiseName,
           -1,
           bindings.MessageHeader.kMessageExpectsResponse);
     }
-    dynamic stopAdvertising(String instanceId,[Function responseFactory = null]) {
-      var params = new _DiscoveryStopAdvertisingParams();
-      params.instanceId = instanceId;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          _Discovery_stopAdvertisingName,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    dynamic startScan(String query,Object handler,[Function responseFactory = null]) {
-      var params = new _DiscoveryStartScanParams();
+    dynamic scan(String query,Object handler,[Function responseFactory = null]) {
+      var params = new _DiscoveryScanParams();
       params.query = query;
       params.handler = handler;
       return _proxyImpl.sendMessageWithRequestId(
           params,
-          _Discovery_startScanName,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    dynamic stopScan(int scanId,[Function responseFactory = null]) {
-      var params = new _DiscoveryStopScanParams();
-      params.scanId = scanId;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          _Discovery_stopScanName,
+          _Discovery_scanName,
           -1,
           bindings.MessageHeader.kMessageExpectsResponse);
     }
@@ -1419,25 +1993,16 @@
   }
 
 
-  DiscoveryStartAdvertisingResponseParams _DiscoveryStartAdvertisingResponseParamsFactory(String instanceId, Error err) {
-    var mojo_factory_result = new DiscoveryStartAdvertisingResponseParams();
+  DiscoveryAdvertiseResponseParams _DiscoveryAdvertiseResponseParamsFactory(List<int> instanceId, Object closer, Error err) {
+    var mojo_factory_result = new DiscoveryAdvertiseResponseParams();
     mojo_factory_result.instanceId = instanceId;
+    mojo_factory_result.closer = closer;
     mojo_factory_result.err = err;
     return mojo_factory_result;
   }
-  DiscoveryStopAdvertisingResponseParams _DiscoveryStopAdvertisingResponseParamsFactory(Error err) {
-    var mojo_factory_result = new DiscoveryStopAdvertisingResponseParams();
-    mojo_factory_result.err = err;
-    return mojo_factory_result;
-  }
-  DiscoveryStartScanResponseParams _DiscoveryStartScanResponseParamsFactory(int scanId, Error err) {
-    var mojo_factory_result = new DiscoveryStartScanResponseParams();
-    mojo_factory_result.scanId = scanId;
-    mojo_factory_result.err = err;
-    return mojo_factory_result;
-  }
-  DiscoveryStopScanResponseParams _DiscoveryStopScanResponseParamsFactory(Error err) {
-    var mojo_factory_result = new DiscoveryStopScanResponseParams();
+  DiscoveryScanResponseParams _DiscoveryScanResponseParamsFactory(Object closer, Error err) {
+    var mojo_factory_result = new DiscoveryScanResponseParams();
+    mojo_factory_result.closer = closer;
     mojo_factory_result.err = err;
     return mojo_factory_result;
   }
@@ -1450,16 +2015,16 @@
     }
     assert(_impl != null);
     switch (message.header.type) {
-      case _Discovery_startAdvertisingName:
-        var params = _DiscoveryStartAdvertisingParams.deserialize(
+      case _Discovery_advertiseName:
+        var params = _DiscoveryAdvertiseParams.deserialize(
             message.payload);
-        var response = _impl.startAdvertising(params.service,params.visibility,_DiscoveryStartAdvertisingResponseParamsFactory);
+        var response = _impl.advertise(params.ad,params.visibility,_DiscoveryAdvertiseResponseParamsFactory);
         if (response is Future) {
           return response.then((response) {
             if (response != null) {
               return buildResponseWithId(
                   response,
-                  _Discovery_startAdvertisingName,
+                  _Discovery_advertiseName,
                   message.header.requestId,
                   bindings.MessageHeader.kMessageIsResponse);
             }
@@ -1467,21 +2032,21 @@
         } else if (response != null) {
           return buildResponseWithId(
               response,
-              _Discovery_startAdvertisingName,
+              _Discovery_advertiseName,
               message.header.requestId,
               bindings.MessageHeader.kMessageIsResponse);
         }
         break;
-      case _Discovery_stopAdvertisingName:
-        var params = _DiscoveryStopAdvertisingParams.deserialize(
+      case _Discovery_scanName:
+        var params = _DiscoveryScanParams.deserialize(
             message.payload);
-        var response = _impl.stopAdvertising(params.instanceId,_DiscoveryStopAdvertisingResponseParamsFactory);
+        var response = _impl.scan(params.query,params.handler,_DiscoveryScanResponseParamsFactory);
         if (response is Future) {
           return response.then((response) {
             if (response != null) {
               return buildResponseWithId(
                   response,
-                  _Discovery_stopAdvertisingName,
+                  _Discovery_scanName,
                   message.header.requestId,
                   bindings.MessageHeader.kMessageIsResponse);
             }
@@ -1489,51 +2054,7 @@
         } else if (response != null) {
           return buildResponseWithId(
               response,
-              _Discovery_stopAdvertisingName,
-              message.header.requestId,
-              bindings.MessageHeader.kMessageIsResponse);
-        }
-        break;
-      case _Discovery_startScanName:
-        var params = _DiscoveryStartScanParams.deserialize(
-            message.payload);
-        var response = _impl.startScan(params.query,params.handler,_DiscoveryStartScanResponseParamsFactory);
-        if (response is Future) {
-          return response.then((response) {
-            if (response != null) {
-              return buildResponseWithId(
-                  response,
-                  _Discovery_startScanName,
-                  message.header.requestId,
-                  bindings.MessageHeader.kMessageIsResponse);
-            }
-          });
-        } else if (response != null) {
-          return buildResponseWithId(
-              response,
-              _Discovery_startScanName,
-              message.header.requestId,
-              bindings.MessageHeader.kMessageIsResponse);
-        }
-        break;
-      case _Discovery_stopScanName:
-        var params = _DiscoveryStopScanParams.deserialize(
-            message.payload);
-        var response = _impl.stopScan(params.scanId,_DiscoveryStopScanResponseParamsFactory);
-        if (response is Future) {
-          return response.then((response) {
-            if (response != null) {
-              return buildResponseWithId(
-                  response,
-                  _Discovery_stopScanName,
-                  message.header.requestId,
-                  bindings.MessageHeader.kMessageIsResponse);
-            }
-          });
-        } else if (response != null) {
-          return buildResponseWithId(
-              response,
-              _Discovery_stopScanName,
+              _Discovery_scanName,
               message.header.requestId,
               bindings.MessageHeader.kMessageIsResponse);
         }
@@ -1562,7 +2083,231 @@
     new _DiscoveryServiceDescription();
 }
 
-const int _ScanHandler_updateName = 0;
+const int _Closer_closeName = 0;
+
+
+
+class _CloserServiceDescription implements service_describer.ServiceDescription {
+  dynamic getTopLevelInterface([Function responseFactory]) => null;
+
+  dynamic getTypeDefinition(String typeKey, [Function responseFactory]) => null;
+
+  dynamic getAllTypeDefinitions([Function responseFactory]) => null;
+}
+
+abstract class Closer {
+  static const String serviceName = null;
+  dynamic close([Function responseFactory = null]);
+}
+
+
+class _CloserProxyImpl extends bindings.Proxy {
+  _CloserProxyImpl.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
+
+  _CloserProxyImpl.fromHandle(core.MojoHandle handle) :
+      super.fromHandle(handle);
+
+  _CloserProxyImpl.unbound() : super.unbound();
+
+  static _CloserProxyImpl newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For _CloserProxyImpl"));
+    return new _CloserProxyImpl.fromEndpoint(endpoint);
+  }
+
+  service_describer.ServiceDescription get serviceDescription =>
+    new _CloserServiceDescription();
+
+  void handleResponse(bindings.ServiceMessage message) {
+    switch (message.header.type) {
+      case _Closer_closeName:
+        var r = CloserCloseResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      default:
+        proxyError("Unexpected message type: ${message.header.type}");
+        close(immediate: true);
+        break;
+    }
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "_CloserProxyImpl($superString)";
+  }
+}
+
+
+class _CloserProxyCalls implements Closer {
+  _CloserProxyImpl _proxyImpl;
+
+  _CloserProxyCalls(this._proxyImpl);
+    dynamic close([Function responseFactory = null]) {
+      var params = new _CloserCloseParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Closer_closeName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+}
+
+
+class CloserProxy implements bindings.ProxyBase {
+  final bindings.Proxy impl;
+  Closer ptr;
+
+  CloserProxy(_CloserProxyImpl proxyImpl) :
+      impl = proxyImpl,
+      ptr = new _CloserProxyCalls(proxyImpl);
+
+  CloserProxy.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) :
+      impl = new _CloserProxyImpl.fromEndpoint(endpoint) {
+    ptr = new _CloserProxyCalls(impl);
+  }
+
+  CloserProxy.fromHandle(core.MojoHandle handle) :
+      impl = new _CloserProxyImpl.fromHandle(handle) {
+    ptr = new _CloserProxyCalls(impl);
+  }
+
+  CloserProxy.unbound() :
+      impl = new _CloserProxyImpl.unbound() {
+    ptr = new _CloserProxyCalls(impl);
+  }
+
+  factory CloserProxy.connectToService(
+      bindings.ServiceConnector s, String url, [String serviceName]) {
+    CloserProxy p = new CloserProxy.unbound();
+    s.connectToService(url, p, serviceName);
+    return p;
+  }
+
+  static CloserProxy newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For CloserProxy"));
+    return new CloserProxy.fromEndpoint(endpoint);
+  }
+
+  String get serviceName => Closer.serviceName;
+
+  Future close({bool immediate: false}) => impl.close(immediate: immediate);
+
+  Future responseOrError(Future f) => impl.responseOrError(f);
+
+  Future get errorFuture => impl.errorFuture;
+
+  int get version => impl.version;
+
+  Future<int> queryVersion() => impl.queryVersion();
+
+  void requireVersion(int requiredVersion) {
+    impl.requireVersion(requiredVersion);
+  }
+
+  String toString() {
+    return "CloserProxy($impl)";
+  }
+}
+
+
+class CloserStub extends bindings.Stub {
+  Closer _impl = null;
+
+  CloserStub.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint, [this._impl])
+      : super.fromEndpoint(endpoint);
+
+  CloserStub.fromHandle(core.MojoHandle handle, [this._impl])
+      : super.fromHandle(handle);
+
+  CloserStub.unbound() : super.unbound();
+
+  static CloserStub newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For CloserStub"));
+    return new CloserStub.fromEndpoint(endpoint);
+  }
+
+
+  CloserCloseResponseParams _CloserCloseResponseParamsFactory() {
+    var mojo_factory_result = new CloserCloseResponseParams();
+    return mojo_factory_result;
+  }
+
+  dynamic handleMessage(bindings.ServiceMessage message) {
+    if (bindings.ControlMessageHandler.isControlMessage(message)) {
+      return bindings.ControlMessageHandler.handleMessage(this,
+                                                          0,
+                                                          message);
+    }
+    assert(_impl != null);
+    switch (message.header.type) {
+      case _Closer_closeName:
+        var params = _CloserCloseParams.deserialize(
+            message.payload);
+        var response = _impl.close(_CloserCloseResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Closer_closeName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Closer_closeName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      default:
+        throw new bindings.MojoCodecError("Unexpected message name");
+        break;
+    }
+    return null;
+  }
+
+  Closer get impl => _impl;
+  set impl(Closer d) {
+    assert(_impl == null);
+    _impl = d;
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "CloserStub($superString)";
+  }
+
+  int get version => 0;
+
+  service_describer.ServiceDescription get serviceDescription =>
+    new _CloserServiceDescription();
+}
+
+const int _ScanHandler_onUpdateName = 0;
 
 
 
@@ -1575,8 +2320,8 @@
 }
 
 abstract class ScanHandler {
-  static const String serviceName = "v23::discovery::ScanHandler";
-  void update(ScanUpdate update);
+  static const String serviceName = null;
+  void onUpdate(Object update);
 }
 
 
@@ -1618,14 +2363,14 @@
   _ScanHandlerProxyImpl _proxyImpl;
 
   _ScanHandlerProxyCalls(this._proxyImpl);
-    void update(ScanUpdate update) {
+    void onUpdate(Object update) {
       if (!_proxyImpl.isBound) {
         _proxyImpl.proxyError("The Proxy is closed.");
         return;
       }
-      var params = new _ScanHandlerUpdateParams();
+      var params = new _ScanHandlerOnUpdateParams();
       params.update = update;
-      _proxyImpl.sendMessage(params, _ScanHandler_updateName);
+      _proxyImpl.sendMessage(params, _ScanHandler_onUpdateName);
     }
 }
 
@@ -1717,10 +2462,10 @@
     }
     assert(_impl != null);
     switch (message.header.type) {
-      case _ScanHandler_updateName:
-        var params = _ScanHandlerUpdateParams.deserialize(
+      case _ScanHandler_onUpdateName:
+        var params = _ScanHandlerOnUpdateParams.deserialize(
             message.payload);
-        _impl.update(params.update);
+        _impl.onUpdate(params.update);
         break;
       default:
         throw new bindings.MojoCodecError("Unexpected message name");
@@ -1746,5 +2491,574 @@
     new _ScanHandlerServiceDescription();
 }
 
+const int _Update_isLostName = 0;
+const int _Update_getIdName = 1;
+const int _Update_getInterfaceNameName = 2;
+const int _Update_getAddressesName = 3;
+const int _Update_getAttributeName = 4;
+const int _Update_getAttachmentName = 5;
+const int _Update_getAdvertisementName = 6;
+
+
+
+class _UpdateServiceDescription implements service_describer.ServiceDescription {
+  dynamic getTopLevelInterface([Function responseFactory]) => null;
+
+  dynamic getTypeDefinition(String typeKey, [Function responseFactory]) => null;
+
+  dynamic getAllTypeDefinitions([Function responseFactory]) => null;
+}
+
+abstract class Update {
+  static const String serviceName = null;
+  dynamic isLost([Function responseFactory = null]);
+  dynamic getId([Function responseFactory = null]);
+  dynamic getInterfaceName([Function responseFactory = null]);
+  dynamic getAddresses([Function responseFactory = null]);
+  dynamic getAttribute(String name,[Function responseFactory = null]);
+  dynamic getAttachment(String name,[Function responseFactory = null]);
+  dynamic getAdvertisement([Function responseFactory = null]);
+}
+
+
+class _UpdateProxyImpl extends bindings.Proxy {
+  _UpdateProxyImpl.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
+
+  _UpdateProxyImpl.fromHandle(core.MojoHandle handle) :
+      super.fromHandle(handle);
+
+  _UpdateProxyImpl.unbound() : super.unbound();
+
+  static _UpdateProxyImpl newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For _UpdateProxyImpl"));
+    return new _UpdateProxyImpl.fromEndpoint(endpoint);
+  }
+
+  service_describer.ServiceDescription get serviceDescription =>
+    new _UpdateServiceDescription();
+
+  void handleResponse(bindings.ServiceMessage message) {
+    switch (message.header.type) {
+      case _Update_isLostName:
+        var r = UpdateIsLostResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case _Update_getIdName:
+        var r = UpdateGetIdResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case _Update_getInterfaceNameName:
+        var r = UpdateGetInterfaceNameResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case _Update_getAddressesName:
+        var r = UpdateGetAddressesResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case _Update_getAttributeName:
+        var r = UpdateGetAttributeResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case _Update_getAttachmentName:
+        var r = UpdateGetAttachmentResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      case _Update_getAdvertisementName:
+        var r = UpdateGetAdvertisementResponseParams.deserialize(
+            message.payload);
+        if (!message.header.hasRequestId) {
+          proxyError("Expected a message with a valid request Id.");
+          return;
+        }
+        Completer c = completerMap[message.header.requestId];
+        if (c == null) {
+          proxyError(
+              "Message had unknown request Id: ${message.header.requestId}");
+          return;
+        }
+        completerMap.remove(message.header.requestId);
+        if (c.isCompleted) {
+          proxyError("Response completer already completed");
+          return;
+        }
+        c.complete(r);
+        break;
+      default:
+        proxyError("Unexpected message type: ${message.header.type}");
+        close(immediate: true);
+        break;
+    }
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "_UpdateProxyImpl($superString)";
+  }
+}
+
+
+class _UpdateProxyCalls implements Update {
+  _UpdateProxyImpl _proxyImpl;
+
+  _UpdateProxyCalls(this._proxyImpl);
+    dynamic isLost([Function responseFactory = null]) {
+      var params = new _UpdateIsLostParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Update_isLostName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getId([Function responseFactory = null]) {
+      var params = new _UpdateGetIdParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Update_getIdName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getInterfaceName([Function responseFactory = null]) {
+      var params = new _UpdateGetInterfaceNameParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Update_getInterfaceNameName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getAddresses([Function responseFactory = null]) {
+      var params = new _UpdateGetAddressesParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Update_getAddressesName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getAttribute(String name,[Function responseFactory = null]) {
+      var params = new _UpdateGetAttributeParams();
+      params.name = name;
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Update_getAttributeName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getAttachment(String name,[Function responseFactory = null]) {
+      var params = new _UpdateGetAttachmentParams();
+      params.name = name;
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Update_getAttachmentName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+    dynamic getAdvertisement([Function responseFactory = null]) {
+      var params = new _UpdateGetAdvertisementParams();
+      return _proxyImpl.sendMessageWithRequestId(
+          params,
+          _Update_getAdvertisementName,
+          -1,
+          bindings.MessageHeader.kMessageExpectsResponse);
+    }
+}
+
+
+class UpdateProxy implements bindings.ProxyBase {
+  final bindings.Proxy impl;
+  Update ptr;
+
+  UpdateProxy(_UpdateProxyImpl proxyImpl) :
+      impl = proxyImpl,
+      ptr = new _UpdateProxyCalls(proxyImpl);
+
+  UpdateProxy.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) :
+      impl = new _UpdateProxyImpl.fromEndpoint(endpoint) {
+    ptr = new _UpdateProxyCalls(impl);
+  }
+
+  UpdateProxy.fromHandle(core.MojoHandle handle) :
+      impl = new _UpdateProxyImpl.fromHandle(handle) {
+    ptr = new _UpdateProxyCalls(impl);
+  }
+
+  UpdateProxy.unbound() :
+      impl = new _UpdateProxyImpl.unbound() {
+    ptr = new _UpdateProxyCalls(impl);
+  }
+
+  factory UpdateProxy.connectToService(
+      bindings.ServiceConnector s, String url, [String serviceName]) {
+    UpdateProxy p = new UpdateProxy.unbound();
+    s.connectToService(url, p, serviceName);
+    return p;
+  }
+
+  static UpdateProxy newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For UpdateProxy"));
+    return new UpdateProxy.fromEndpoint(endpoint);
+  }
+
+  String get serviceName => Update.serviceName;
+
+  Future close({bool immediate: false}) => impl.close(immediate: immediate);
+
+  Future responseOrError(Future f) => impl.responseOrError(f);
+
+  Future get errorFuture => impl.errorFuture;
+
+  int get version => impl.version;
+
+  Future<int> queryVersion() => impl.queryVersion();
+
+  void requireVersion(int requiredVersion) {
+    impl.requireVersion(requiredVersion);
+  }
+
+  String toString() {
+    return "UpdateProxy($impl)";
+  }
+}
+
+
+class UpdateStub extends bindings.Stub {
+  Update _impl = null;
+
+  UpdateStub.fromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint, [this._impl])
+      : super.fromEndpoint(endpoint);
+
+  UpdateStub.fromHandle(core.MojoHandle handle, [this._impl])
+      : super.fromHandle(handle);
+
+  UpdateStub.unbound() : super.unbound();
+
+  static UpdateStub newFromEndpoint(
+      core.MojoMessagePipeEndpoint endpoint) {
+    assert(endpoint.setDescription("For UpdateStub"));
+    return new UpdateStub.fromEndpoint(endpoint);
+  }
+
+
+  UpdateIsLostResponseParams _UpdateIsLostResponseParamsFactory(bool lost) {
+    var mojo_factory_result = new UpdateIsLostResponseParams();
+    mojo_factory_result.lost = lost;
+    return mojo_factory_result;
+  }
+  UpdateGetIdResponseParams _UpdateGetIdResponseParamsFactory(List<int> id) {
+    var mojo_factory_result = new UpdateGetIdResponseParams();
+    mojo_factory_result.id = id;
+    return mojo_factory_result;
+  }
+  UpdateGetInterfaceNameResponseParams _UpdateGetInterfaceNameResponseParamsFactory(String interfaceName) {
+    var mojo_factory_result = new UpdateGetInterfaceNameResponseParams();
+    mojo_factory_result.interfaceName = interfaceName;
+    return mojo_factory_result;
+  }
+  UpdateGetAddressesResponseParams _UpdateGetAddressesResponseParamsFactory(List<String> addresses) {
+    var mojo_factory_result = new UpdateGetAddressesResponseParams();
+    mojo_factory_result.addresses = addresses;
+    return mojo_factory_result;
+  }
+  UpdateGetAttributeResponseParams _UpdateGetAttributeResponseParamsFactory(String attribute) {
+    var mojo_factory_result = new UpdateGetAttributeResponseParams();
+    mojo_factory_result.attribute = attribute;
+    return mojo_factory_result;
+  }
+  UpdateGetAttachmentResponseParams _UpdateGetAttachmentResponseParamsFactory(core.MojoDataPipeConsumer data) {
+    var mojo_factory_result = new UpdateGetAttachmentResponseParams();
+    mojo_factory_result.data = data;
+    return mojo_factory_result;
+  }
+  UpdateGetAdvertisementResponseParams _UpdateGetAdvertisementResponseParamsFactory(Advertisement ad) {
+    var mojo_factory_result = new UpdateGetAdvertisementResponseParams();
+    mojo_factory_result.ad = ad;
+    return mojo_factory_result;
+  }
+
+  dynamic handleMessage(bindings.ServiceMessage message) {
+    if (bindings.ControlMessageHandler.isControlMessage(message)) {
+      return bindings.ControlMessageHandler.handleMessage(this,
+                                                          0,
+                                                          message);
+    }
+    assert(_impl != null);
+    switch (message.header.type) {
+      case _Update_isLostName:
+        var params = _UpdateIsLostParams.deserialize(
+            message.payload);
+        var response = _impl.isLost(_UpdateIsLostResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Update_isLostName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Update_isLostName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case _Update_getIdName:
+        var params = _UpdateGetIdParams.deserialize(
+            message.payload);
+        var response = _impl.getId(_UpdateGetIdResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Update_getIdName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Update_getIdName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case _Update_getInterfaceNameName:
+        var params = _UpdateGetInterfaceNameParams.deserialize(
+            message.payload);
+        var response = _impl.getInterfaceName(_UpdateGetInterfaceNameResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Update_getInterfaceNameName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Update_getInterfaceNameName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case _Update_getAddressesName:
+        var params = _UpdateGetAddressesParams.deserialize(
+            message.payload);
+        var response = _impl.getAddresses(_UpdateGetAddressesResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Update_getAddressesName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Update_getAddressesName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case _Update_getAttributeName:
+        var params = _UpdateGetAttributeParams.deserialize(
+            message.payload);
+        var response = _impl.getAttribute(params.name,_UpdateGetAttributeResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Update_getAttributeName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Update_getAttributeName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case _Update_getAttachmentName:
+        var params = _UpdateGetAttachmentParams.deserialize(
+            message.payload);
+        var response = _impl.getAttachment(params.name,_UpdateGetAttachmentResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Update_getAttachmentName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Update_getAttachmentName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      case _Update_getAdvertisementName:
+        var params = _UpdateGetAdvertisementParams.deserialize(
+            message.payload);
+        var response = _impl.getAdvertisement(_UpdateGetAdvertisementResponseParamsFactory);
+        if (response is Future) {
+          return response.then((response) {
+            if (response != null) {
+              return buildResponseWithId(
+                  response,
+                  _Update_getAdvertisementName,
+                  message.header.requestId,
+                  bindings.MessageHeader.kMessageIsResponse);
+            }
+          });
+        } else if (response != null) {
+          return buildResponseWithId(
+              response,
+              _Update_getAdvertisementName,
+              message.header.requestId,
+              bindings.MessageHeader.kMessageIsResponse);
+        }
+        break;
+      default:
+        throw new bindings.MojoCodecError("Unexpected message name");
+        break;
+    }
+    return null;
+  }
+
+  Update get impl => _impl;
+  set impl(Update d) {
+    assert(_impl == null);
+    _impl = d;
+  }
+
+  String toString() {
+    var superString = super.toString();
+    return "UpdateStub($superString)";
+  }
+
+  int get version => 0;
+
+  service_describer.ServiceDescription get serviceDescription =>
+    new _UpdateServiceDescription();
+}
+
 
 
diff --git a/mojoconfig b/mojoconfig
index 9e2c0d5..1aeabf8 100644
--- a/mojoconfig
+++ b/mojoconfig
@@ -4,6 +4,7 @@
   'dev_servers': [
     {
       'host': 'https://mojo.v.io/',
+      'port': 32000,
       'mappings': [
         ('', [
           '@{DISCOVERY_BUILD_DIR}',
diff --git a/mojom/vanadium/discovery.mojom b/mojom/vanadium/discovery.mojom
index 0ae5c2d..41786cb 100644
--- a/mojom/vanadium/discovery.mojom
+++ b/mojom/vanadium/discovery.mojom
@@ -6,79 +6,133 @@
 module discovery;
 
 // Copied from v.io/v23/discovery/types.vdl
-struct Service {
-  // The universal unique identifier of a service instance.
-  // If this is not specified, a random 128 bit (16 byte) UUID will be used.
-  string? InstanceId;
-  // Optional name of the service instance.
-  string? InstanceName;
-  // The interface that the service implements.
+//
+// Advertisement represents a feed into advertiser to broadcast its contents
+// to scanners.
+//
+// A large advertisement may require additional RPC calls causing delay in
+// discovery. We limit the maximum size of an advertisement to 512 bytes
+// excluding id and attachments.
+struct Advertisement {
+  const int32 ID_LEN = 16;
+
+  // Universal unique identifier of the advertisement.
+  // If this is not specified, a random unique identifier will be assigned.
+  array<uint8, 16>? id;
+
+  // Interface name that the advertised service implements.
   // E.g., 'v.io/v23/services/vtrace.Store'.
-  string InterfaceName;
-  // The service attributes.
+  string interface_name;
+
+  // Addresses (vanadium object names) that the advertised service is served on.
+  // E.g., '/host:port/a/b/c', '/ns.dev.v.io:8101/blah/blah'.
+  array<string> addresses;
+
+  // Attributes as a key/value pair.
   // E.g., {'resolution': '1024x768'}.
-  map<string, string>? Attrs;
-  // The addresses that the service is served on.
-  // E.g., '/host:port/a/b/c'.
-  array<string> Addrs;
-  // The service attachments.
+  //
+  // The key must be US-ASCII printable characters, excluding the '=' character
+  // and should not start with '_' character.
+  map<string, string>? attributes;
+
+  // Attachments as a key/value pair.
   // E.g., {'thumbnail': binary_data }.
-  map<string, array<uint8>>? Attachments;
+  //
+  // Unlike attributes, attachments are for binary data and they are not queryable.
+  // We limit the maximum size of a single attachment to 4K bytes.
+  //
+  // The key must be US-ASCII printable characters, excluding the '=' character
+  // and should not start with '_' character.
+  map<string, array<uint8>>? attachments;
 };
 
-enum UpdateType {
-  found = 1,
-  lost,
-};
-
-struct ScanUpdate {
-  Service service;
-  UpdateType update_type;
-};
-
+// Error wraps verror.
 struct Error {
-  string id;
-  int32 action;
+  string id;  // empty string means no error
+  uint32 action_code;
   string msg;
 };
 
-// Discovery provides Vanadium discovery operations.
+// Discovery provides Vanadium discovery service.
 [ServiceName="v23::discovery::Discovery"]
 interface Discovery {
-  // StartAdvertising advertises the service to be discovered by "Scanner"
-  // implementations. visibility is used to limit the principals that can see
-  // the advertisement. An empty set means that there are no restrictions on
-  // visibility (i.e, equivalent to []security.BlessingPattern{security.AllPrincipals}).
+  // Broadcasts the advertisement to be discovered by |Scan| operations.
+  //
+  // |visibility| is used to limit the principals that can see the advertisement. An
+  // empty set means that there are no restrictions on visibility (i.e, equivalent
+  // to []security.BlessingPattern{security.AllPrincipals}).
+  //
+  // If the advertisement id is not specified, a random unique a random unique identifier
+  // will be assigned. The advertisement should not be changed while it is being advertised.
   //
   // It is an error to have simultaneously active advertisements for two identical
-  // instances (service.InstanceUuid).
-  StartAdvertising(Service service, array<string>? visibility) => (string instance_id, Error? err);
-
-  // StopAdvertising stops the advertisement associated with the given instance id.
-  StopAdvertising(string instance_id) => (Error? Err);
-
-  // Scan scans for services matching the query passed and calls ScanHandler with updates.
+  // instances (Advertisement.id).
   //
-  // The query is a WHERE expression of syncQL query against scanned services, where
-  // keys are InstanceUuids and values are Service.
+  // Advertising will continue until the returned |closer| is closed.
+  Advertise(Advertisement ad, array<string>? visibility) => (array<uint8, 16>? instance_id, Closer? closer, Error? err);
+
+  // Scans advertisements that match the |query| and calls the |handler| with updates.
+  //
+  // Scan excludes the advertisements that are advertised from the same discovery
+  // instance.
+  //
+  // The |query| is a WHERE expression of a syncQL query against advertisements, where
+  // key is Advertisement.id and value is Advertisement.
   //
   // Examples
   //
-  //    v.InstanceName = "v.io/i"
-  //    v.InstanceName = "v.io/i" AND v.Attrs["a"] = "v"
-  //    v.Attrs["a"] = "v1" OR v.Attrs["a"] = "v2"
+  //    v.InterfaceName = "v.io/i"
+  //    v.InterfaceName = "v.io/i" AND v.Attributes["a"] = "v"
+  //    v.Attributes["a"] = "v1" OR v.Attributes["a"] = "v2"
   //
   // SyncQL tutorial at:
-  //    https://github.com/vanadium/docs/blob/master/tutorials/syncql-tutorial.md
-  StartScan(string query, ScanHandler handler) => (uint32 scan_id, Error? err);
-
-  // StopScan stops the scanning associated with the given scan id.
-  StopScan(uint32 scan_id) => (Error? err);
+  //    https://vanadium.github.io/tutorials/syncbase/syncql-tutorial.html
+  //
+  // Scanning will continue until the returned |closer| is closed.
+  Scan(string query, ScanHandler handler) => (Closer? closer, Error? err);
 };
 
-// ScanHandler is used to pass updates about services that are found/lost during the scan.
-[ServiceName="v23::discovery::ScanHandler"]
+// Closer wraps the Close method.
+interface Closer {
+  Close() => ();
+};
+
+// ScanHandler is used to pass advertisements that are found/lost during the scan.
 interface ScanHandler {
-  // Update will be called when a Service is found or lost.
-  Update(ScanUpdate update);
+  // Called with each discovery update.
+  OnUpdate(Update update);
+};
+
+// Update is the interface for a discovery update.
+interface Update {
+  // Returns true when this update corresponds to an advertisement
+  // that led to a previous update vanishing.
+  IsLost() => (bool lost);
+
+  // Returns the universal unique identifier of the advertisement.
+  GetId() => (array<uint8, 16> id);
+
+  // Returns the interface name that the service implements.
+  GetInterfaceName() => (string interface_name);
+
+  // Returns the addresses (vanadium object names) that the service
+  // is served on.
+  GetAddresses() => (array<string> addresses);
+
+  // Returns the named attribute. An empty string is returned if
+  // not found.
+  GetAttribute(string name) => (string attribute);
+
+  // Returns the channel on which the named attachment can be read.
+  // A zero-length data is returned if not found.
+  //
+  // This may do RPC calls if the attachment is not fetched yet.
+  //
+  // Attachments may not be available when this update is for lost advertisement.
+  GetAttachment(string name) => (handle<data_pipe_consumer> data);
+
+  // Returns the advertisement that this update corresponds to.
+  //
+  // The returned advertisement may not include all attachments.
+  GetAdvertisement() => (Advertisement ad);
 };