Skip to content

Commit 4f6bdce

Browse files
authored
Setup trace ffx unix pipe (google#1277)
* [fuchsia] Create AGI to ffx unix socket bridge.
1 parent e9adf18 commit 4f6bdce

File tree

16 files changed

+241
-52
lines changed

16 files changed

+241
-52
lines changed

core/cc/fuchsia/zircon_socket_connection.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,65 @@
2121
#include <errno.h>
2222
#include <zircon/status.h>
2323

24+
#include <thread>
25+
2426
#include "core/cc/log.h"
2527

28+
#define ERR_IF_COND(cond, ...) \
29+
if ((cond)) { \
30+
GAPID_ERROR(__VA_ARGS__); \
31+
}
32+
2633
namespace core {
2734

2835
ZirconSocketConnection::~ZirconSocketConnection() { mSocket.reset(); }
2936

3037
size_t ZirconSocketConnection::send(const void* data, size_t size) {
3138
size_t bytes_written = 0;
3239
zx_status_t status = mSocket.write(0u, data, size, &bytes_written);
33-
if (status != ZX_OK) {
34-
GAPID_ERROR("Failed to write data to Zircon socket: %s",
35-
zx_status_get_string(status));
36-
}
40+
ERR_IF_COND(status != ZX_OK, "Failed to write data to Zircon socket: %s",
41+
zx_status_get_string(status));
3742
return bytes_written;
3843
}
3944

40-
size_t ZirconSocketConnection::recv(void* data, size_t size) {
41-
size_t bytes_read = 0;
42-
zx_status_t status = mSocket.read(0u, data, size, &bytes_read);
43-
if (status != ZX_OK) {
44-
GAPID_ERROR("Failed to read data from Zircon socket: %s",
45-
zx_status_get_string(status));
46-
}
47-
return bytes_read;
45+
size_t ZirconSocketConnection::recv(void* data, const size_t size) {
46+
const auto p = static_cast<uint8_t*>(data);
47+
size_t total_bytes_read = 0;
48+
zx_status_t read_status = ZX_ERR_INTERNAL;
49+
zx_status_t wait_status = ZX_ERR_INTERNAL;
50+
zx_signals_t observed_signal = 0;
51+
do {
52+
size_t bytes_read = 0;
53+
read_status = mSocket.read(0u, p + total_bytes_read,
54+
size - total_bytes_read, &bytes_read);
55+
switch (read_status) {
56+
case ZX_OK:
57+
total_bytes_read += bytes_read;
58+
break;
59+
case ZX_ERR_SHOULD_WAIT:
60+
wait_status =
61+
mSocket.wait_one(ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
62+
zx::time::infinite(), &observed_signal);
63+
64+
if (wait_status != ZX_OK || observed_signal & ZX_SOCKET_PEER_CLOSED) {
65+
GAPID_ERROR("ZirconSocketConnection wait_status: %s observed: %d",
66+
zx_status_get_string(wait_status), observed_signal);
67+
return 0;
68+
}
69+
break;
70+
default:
71+
GAPID_ERROR("ZirconSocketConnection unexpected read_status: %s",
72+
zx_status_get_string(read_status));
73+
return 0;
74+
}
75+
} while ((read_status == ZX_OK || observed_signal & ZX_SOCKET_READABLE) &&
76+
total_bytes_read < size);
77+
78+
ERR_IF_COND(total_bytes_read != size,
79+
"Failed to read %zu bytes from Zircon socket. read_status: %s",
80+
size, zx_status_get_string(read_status));
81+
82+
return total_bytes_read;
4883
}
4984

5085
std::unique_ptr<Connection> ZirconSocketConnection::accept(int timeoutMs) {

core/cc/fuchsia/zircon_socket_connection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ZirconSocketConnection final : public Connection {
3737
ZirconSocketConnection& operator=(const ZirconSocketConnection&) = delete;
3838

3939
// Implementation of the Connection interface.
40-
size_t send(const void* data, size_t size) override;
40+
size_t send(const void* data, const size_t size) override;
4141
size_t recv(void* data, size_t size) override;
4242
const char* error() override;
4343

core/os/fuchsia/ffx/bind.go

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -160,26 +160,40 @@ func (b *binding) TraceProviders(ctx context.Context) ([]string, error) {
160160

161161
// StartTrace implements the fuchsia.Device interface and starts a Fuchsia trace.
162162
func (b *binding) StartTrace(ctx context.Context, options *service.TraceOptions, traceFile file.Path, stop task.Signal, ready task.Task) error {
163-
var categoriesArg string
164-
165-
// Initialize shell command.
166-
cmd := b.Command("trace", "start", "--output", traceFile.System())
167-
168-
// Extract trace options and append arguments to command.
169-
if options != nil {
170-
if durationSecs := int(options.Duration); durationSecs > 0 {
171-
cmd = cmd.With("--duration", strconv.Itoa(durationSecs))
163+
var cmd shell.Cmd
164+
switch t := options.GetType(); t {
165+
case service.TraceType_Graphics:
166+
if fuchsiaConfig := options.GetFuchsiaTraceConfig(); fuchsiaConfig != nil {
167+
// Initialize shell command.
168+
cmd = b.Command("agis", "listen", strconv.FormatInt(int64(fuchsiaConfig.GetGlobalId()), 10))
169+
} else {
170+
return fmt.Errorf("fuchsiaConfig is nil for graphics trace")
172171
}
172+
case service.TraceType_Fuchsia:
173+
var categoriesArg string
174+
// Initialize shell command.
175+
cmd = b.Command("trace", "start", "--output", traceFile.System())
176+
177+
// Extract trace options and append arguments to command.
178+
if options != nil {
179+
if durationSecs := int(options.Duration); durationSecs > 0 {
180+
cmd = cmd.With("--duration", strconv.Itoa(durationSecs))
181+
}
173182

174-
// ffx expects a comma delimited list of trace categories.
175-
if fuchsiaConfig := options.GetFuchsiaTraceConfig(); fuchsiaConfig != nil {
176-
categoriesArg = strings.Join(fuchsiaConfig.Categories, ",")
177-
if len(categoriesArg) > 0 {
178-
cmd = cmd.With("--categories", categoriesArg)
183+
// ffx expects a comma delimited list of trace categories.
184+
if fuchsiaConfig := options.GetFuchsiaTraceConfig(); fuchsiaConfig != nil {
185+
categories := fuchsiaConfig.GetCategories()
186+
categoriesArg = strings.Join(categories, ",")
187+
if len(categoriesArg) > 0 {
188+
cmd = cmd.With("--categories", categoriesArg)
189+
}
179190
}
180191
}
192+
default:
193+
return fmt.Errorf("Unknown Fuchsia trace type: %d", t)
181194
}
182195

196+
log.I(ctx, "StartTrace is calling `ffx agis listen <global_id>`")
183197
stdout, err := cmd.Call(ctx)
184198

185199
if err != nil {

gapic/src/main/com/google/gapid/perfetto/views/FuchsiaTraceConfigDialog.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,13 @@ public static String getConfigSummary(Settings settings) {
9494
}
9595
}
9696

97-
public static Service.FuchsiaTraceConfig.Builder getConfig(Settings settings) {
97+
public static Service.FuchsiaTraceConfig.Builder getCategories(Settings settings) {
9898
return Service.FuchsiaTraceConfig.newBuilder()
99-
.addAllCategories(settings.fuchsiaTracing().getCategoriesList());
99+
.addAllCategories(settings.fuchsiaTracing().getCategoriesList());
100+
}
101+
102+
public static Service.FuchsiaTraceConfig.Builder getGlobalId(int globalId) {
103+
return Service.FuchsiaTraceConfig.newBuilder().setGlobalId(globalId);
100104
}
101105

102106
@Override

gapic/src/main/com/google/gapid/server/Tracer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ protected void onUiThread(Throwable result) {
7171
}
7272
});
7373

74+
// Send the trace request to gapis.
7475
sender.send(Service.TraceRequest.newBuilder()
7576
.setInitialize(request.options)
7677
.build());

gapic/src/main/com/google/gapid/settings.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ message Perfetto {
203203

204204
message FuchsiaTracing {
205205
repeated string categories = 1;
206+
int32 global_id = 2;
206207
}
207208

208209
message Settings {

gapic/src/main/com/google/gapid/views/TracerDialog.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,18 @@ public static void showTracingDialog(
190190
private static void showTracingDialog(
191191
TraceType type, Client client, Shell shell, Models models, Widgets widgets) {
192192
models.analytics.postInteraction(View.Trace, ClientAction.Show);
193+
193194
TraceInputDialog input =
194195
new TraceInputDialog(shell, type, models, widgets, models.devices::loadDevices);
196+
195197
if (loadDevicesAndShowDialog(input, models) == Window.OK) {
196-
TraceProgressDialog progress = new TraceProgressDialog(
197-
shell, models.analytics, input.getValue(), widgets.theme);
198+
TraceProgressDialog progress =
199+
new TraceProgressDialog(shell, models.analytics, input.getValue(), widgets.theme);
200+
198201
Tracer.Trace trace = Tracer.trace(client, shell, input.getValue(), progress);
202+
199203
progress.setTrace(trace);
204+
200205
if (progress.open() == Window.OK && progress.successful()) {
201206
models.capture.loadCapture(input.getValue().output);
202207
}
@@ -429,7 +434,9 @@ public TraceInput(Composite parent, TraceType type, Models models, Widgets widge
429434
createGroup(this, "Application", new GridLayout(2, false)),
430435
new GridData(GridData.FILL_HORIZONTAL));
431436
targetLabel = createLabel(appGroup, TARGET_LABEL + ":");
437+
432438
traceTarget = withLayoutData(new ActionTextbox(appGroup, trace.getUri()) {
439+
433440
@Override
434441
protected String createAndShowDialog(String current) {
435442
DeviceCaptureInfo dev = getSelectedDevice();
@@ -450,6 +457,7 @@ protected String createAndShowDialog(String current) {
450457
}
451458
return null;
452459
}
460+
453461
}, new GridData(SWT.FILL, SWT.FILL, true, false));
454462

455463
createLabel(appGroup, "Additional Arguments:");
@@ -1070,11 +1078,26 @@ public TraceRequest getTraceRequest(Settings settings) {
10701078
options.setClearCache(clearCache.getSelection());
10711079
}
10721080

1081+
if (dev.isFuchsia()) {
1082+
if(type == TraceType.System) {
1083+
options.setFuchsiaTraceConfig(FuchsiaTraceConfigDialog.getCategories(settings));
1084+
} else if (type == TraceType.Vulkan) {
1085+
String uri = trace.getUri();
1086+
if (!uri.isEmpty()) {
1087+
String[] tokens = uri.split("\\s+");
1088+
int globalId = Integer.parseInt(tokens[0]);
1089+
options.setFuchsiaTraceConfig(FuchsiaTraceConfigDialog.getGlobalId(globalId));
1090+
} else {
1091+
throw new AssertionError("No global ID found in URI");
1092+
}
1093+
} else {
1094+
throw new AssertionError("Invalid Fuchsia trace type");
1095+
}
1096+
}
1097+
10731098
if (type == TraceType.System) {
10741099
options.setDuration(duration.getSelection());
1075-
if (dev.isFuchsia()) {
1076-
options.setFuchsiaTraceConfig(FuchsiaTraceConfigDialog.getConfig(settings));
1077-
} else {
1100+
if (!dev.isFuchsia()) {
10781101
int durationMs = duration.getSelection() * 1000;
10791102
// TODO: this isn't really unlimited.
10801103
durationMs = (durationMs == 0) ? (int)MINUTES.toMillis(10) : durationMs;

gapii/cc/connection_header.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ConnectionHeader::ConnectionHeader()
3131

3232
bool ConnectionHeader::read(core::StreamReader* reader) {
3333
if (!reader->read(mMagic)) {
34+
GAPID_WARNING("ConnectionHeader read into mMagic (4 bytes), failed.");
3435
return false;
3536
}
3637
if (mMagic[0] != 's' || mMagic[1] != 'p' || mMagic[2] != 'y' ||
@@ -43,6 +44,7 @@ bool ConnectionHeader::read(core::StreamReader* reader) {
4344
// TODO: Endian-swap data if GAPII is running on a big-endian architecture.
4445

4546
if (!reader->read(mVersion)) {
47+
GAPID_WARNING("ConnectionHeader read into mVersion, failed.");
4648
return false;
4749
}
4850

@@ -58,6 +60,8 @@ bool ConnectionHeader::read(core::StreamReader* reader) {
5860
if (!reader->read(mObserveFrameFrequency) || !reader->read(mStartFrame) ||
5961
!reader->read(mNumFrames) || !reader->read(mAPIs) ||
6062
!reader->read(mFlags)) {
63+
GAPID_WARNING(
64+
"ConnectionHeader bulk of header information read has FAILED");
6165
return false;
6266
}
6367

gapii/cc/spy.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ Spy::Spy()
174174
#endif // TARGET_OS
175175
if (mConnection->write("gapii", 5) != 5) { // handshake string
176176
GAPID_FATAL("Couldn't send \"gapii\" handshake string");
177+
} else {
178+
GAPID_INFO("Wrote \"gapii\" to vulkan socket.");
177179
}
178180
GAPID_INFO("Connection made");
179181
}
@@ -322,7 +324,8 @@ zx_handle_t Spy::AgisRegisterAndRetrieve(uint64_t client_id) {
322324
register_result.error_value().FormatDescription().c_str());
323325
}
324326

325-
// Retrieve Vulkan socket.
327+
// Issue hanging get to retrieve the Vulkan socket.
328+
GAPID_INFO("Gapii - Issuing hanging get to wait for Vulkan socket");
326329
fidl::Result<fuchsia_gpu_agis::ComponentRegistry::GetVulkanSocket>
327330
socket_result = mAgisComponentRegistry->GetVulkanSocket(client_id);
328331
if (socket_result.is_error()) {
@@ -332,6 +335,8 @@ zx_handle_t Spy::AgisRegisterAndRetrieve(uint64_t client_id) {
332335
zx::socket vulkan_socket(std::move(socket_result->socket()));
333336
if (!vulkan_socket.is_valid()) {
334337
GAPID_ERROR("Spy(fuchsia) GetVulkanSocket() - invalid socket");
338+
} else {
339+
GAPID_INFO("Gapii - Retrieved valid Vulkan socket.");
335340
}
336341

337342
// Release socket back to the caller.

gapii/client/adb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ type Process struct {
5353
Options Options
5454

5555
// The connection
56-
conn net.Conn
56+
Conn net.Conn
5757
}
5858

5959
// Start launches an activity on an android device with the GAPII interceptor

0 commit comments

Comments
 (0)