aboutsummaryrefslogtreecommitdiff
path: root/server/rpc_server.go
blob: febcdef66fae9258313e866709564f8f7b9feb78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"bytes"
	"net"

	"android.googlesource.com/platform/tools/gpu/atom"
	"android.googlesource.com/platform/tools/gpu/binary"
	"android.googlesource.com/platform/tools/gpu/binary/cyclic"
	"android.googlesource.com/platform/tools/gpu/binary/registry"
	"android.googlesource.com/platform/tools/gpu/binary/schema"
	"android.googlesource.com/platform/tools/gpu/binary/vle"
	"android.googlesource.com/platform/tools/gpu/builder"
	"android.googlesource.com/platform/tools/gpu/database"
	"android.googlesource.com/platform/tools/gpu/log"
	"android.googlesource.com/platform/tools/gpu/memory"
	"android.googlesource.com/platform/tools/gpu/replay"
	"android.googlesource.com/platform/tools/gpu/service"
)

type rpcServer struct {
	service.Resolver
	ReplayManager *replay.Manager
}

func (s rpcServer) ListenAndServe(addr string, mtu int, logger log.Logger) error {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}

	for {
		if conn, err := listener.Accept(); err == nil {
			service.BindServer(conn, conn, mtu, logger.Fork(), &s)
		} else {
			return err
		}
	}
}

// Compliance with the service.RPC interface.

// The GetSchema returns the type and constant schema descriptions for all
// objects used in the api.
// This includes all the types included in or referenced from the atom stream.
func (s rpcServer) GetSchema(l log.Logger) (service.ClassPtrArray, error) {
	classes := make(service.ClassPtrArray, 0, registry.Global.Count())
	registry.Global.Visit(func(c binary.Class) {
		class := schema.Lookup(c.ID())
		if class != nil {
			classes = append(classes, class)
		}
	})
	return classes, nil
}

// Import imports capture data emitted by the graphics spy, returning the new
// capture identifier.
func (s rpcServer) Import(name string, data service.U8Array, l log.Logger) (service.CaptureId, error) {
	atoms := atom.List{}
	if err := atoms.Decode(cyclic.Decoder(vle.Reader(bytes.NewBuffer(data)))); err != nil {
		if len(atoms) == 0 {
			return service.CaptureId{}, err
		}
		l.Warningf("Decode of capture errored after decoding %d atoms: %v", len(atoms), err)
	}
	id, err := builder.ImportCapture(name, atoms, s.Database, l)
	if err != nil {
		return service.CaptureId{}, err
	}
	return id, nil
}

// GetCaptures returns the full list of capture identifiers avaliable on the server.
func (s rpcServer) GetCaptures(l log.Logger) (service.CaptureIdArray, error) {
	return builder.Captures(s.Database, l)
}

// GetDevices returns the full list of replay devices avaliable to the server.
// These include local replay devices and any connected Android devices.
// This list may change over time, as devices are connected and disconnected.
func (s rpcServer) GetDevices(l log.Logger) (service.DeviceIdArray, error) {
	devices := s.ReplayManager.Devices()
	ids := make(service.DeviceIdArray, len(devices))
	for i, d := range devices {
		ids[i] = d.ID()
	}
	return ids, nil
}

// GetState returns an identifier to a binary blob containing the graphics state
// immediately following the atom after.
// The binary blob can be fetched with a call to ResolveBinary, and decoded
// using the capture's schema.
func (s rpcServer) GetState(
	captureID service.CaptureId,
	at uint64,
	l log.Logger) (service.BinaryId, error) {

	id, err := database.Store(&builder.GetState{
		Capture: captureID,
		After:   atom.ID(at),
	}, s.Database, l)
	return service.BinaryId{ID: id}, err
}

// GetHierarchy returns the atom hierarchy identifier for the given capture.
// Currently there is only one hierarchy per capture, but this is likely to
// change in the future.
func (s rpcServer) GetHierarchy(
	captureID service.CaptureId,
	l log.Logger) (service.HierarchyId, error) {

	id, err := database.Store(&builder.GetHierarchy{
		Capture: captureID,
	}, s.Database, l)
	return service.HierarchyId{ID: id}, err
}

// GetMemoryInfo returns the MemoryInfo identifier describing the memory state
// for the given capture and memory range, immediately following the atom after.
func (s rpcServer) GetMemoryInfo(
	captureID service.CaptureId,
	after uint64,
	rng service.MemoryRange,
	l log.Logger) (service.MemoryInfoId, error) {

	id, err := database.Store(&builder.GetMemoryInfo{
		Capture: captureID,
		After:   atom.ID(after),
		Range:   memory.Range{Base: memory.Pointer(rng.Base), Size: rng.Size},
	}, s.Database, l)
	return service.MemoryInfoId{ID: id}, err
}

// GetFramebufferColor returns the ImageInfo identifier describing the bound
// color buffer for the given device, capture and graphics API immediately
// following the atom after. The provided RenderSettings structure can be used
// to adjust maximum desired dimensions of the image, as well as applying debug
// visualizations.
func (s rpcServer) GetFramebufferColor(
	deviceID service.DeviceId,
	captureID service.CaptureId,
	apiID service.ApiId,
	after uint64,
	settings service.RenderSettings,
	l log.Logger) (service.ImageInfoId, error) {

	id, err := database.Store(&builder.GetFramebufferColor{
		Device:   deviceID,
		Capture:  captureID,
		API:      apiID,
		After:    atom.ID(after),
		Settings: settings,
	}, s.Database, l)
	return service.ImageInfoId{ID: id}, err
}

// GetFramebufferDepth returns the ImageInfo identifier describing the bound
// depth buffer for the given device, capture and graphics API immediately
// following the atom after.
func (s rpcServer) GetFramebufferDepth(
	deviceID service.DeviceId,
	captureID service.CaptureId,
	apiID service.ApiId,
	after uint64,
	l log.Logger) (service.ImageInfoId, error) {

	id, err := database.Store(&builder.GetFramebufferDepth{
		Device:  deviceID,
		Capture: captureID,
		API:     apiID,
		After:   atom.ID(after),
	}, s.Database, l)
	return service.ImageInfoId{ID: id}, err
}

// GetTimingInfo performs timings of the given capture on the given device and
// capture, returning an identifier to the results.
// This function is experimental and will change signature.
func (s rpcServer) GetTimingInfo(
	deviceID service.DeviceId,
	captureID service.CaptureId,
	mask service.TimingMask,
	l log.Logger) (service.TimingInfoId, error) {

	id, err := database.Store(&builder.GetTimingInfo{
		Device:     deviceID,
		Capture:    captureID,
		TimingMask: mask,
	}, s.Database, l)
	return service.TimingInfoId{ID: id}, err
}

// PrerenderFramebuffers renders the framebuffer contents after each of the
// given atoms of interest in the given capture on the given device, resized to
// fit within the given dimensions while keeping the respective framebuffers
// original aspect ratio. This function doesn't return any data, as it is used
// to pre-populate the cache of framebuffer thumbnails that later get queried by
// the client.
// This function is experimental and may change signature.
func (s rpcServer) PrerenderFramebuffers(
	deviceID service.DeviceId,
	captureID service.CaptureId,
	apiID service.ApiId,
	width, height uint32,
	atomIDs service.U64Array,
	l log.Logger) (service.BinaryId, error) {

	id, err := database.Store(&builder.PrerenderFramebuffers{
		Device:  deviceID,
		Capture: captureID,
		API:     apiID,
		Width:   width,
		Height:  height,
		AtomIDs: atomIDs,
	}, s.Database, l)
	return service.BinaryId{ID: id}, err
}

// ReplaceAtom creates and new capture based on an existing capture, but with
// a single atom replaced.
func (s rpcServer) ReplaceAtom(
	capture service.CaptureId,
	atomID uint64,
	atomType uint16,
	data service.Binary,
	l log.Logger) (service.CaptureId, error) {

	id, err := database.Store(&builder.ReplaceAtom{
		Capture: capture,
		Atom:    atom.ID(atomID),
		Type:    atom.TypeID(atomType),
		Data:    data,
	}, s.Database, l)
	return service.CaptureId{ID: id}, err
}