Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote SSH connection support #1898

Merged
merged 10 commits into from
May 23, 2018
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ copy_to(
"//cmd/gapis",
"//cmd/gapit",
"//tools/build:build.properties",
"//cmd/device-info:device-info",
] + select({
"//tools/build:no-android": [],
"//conditions:default": [
Expand Down
1 change: 1 addition & 0 deletions cmd/gapis/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ go_library(
"//core/os/android/adb:go_default_library",
"//core/os/device/bind:go_default_library",
"//core/os/device/host:go_default_library",
"//core/os/device/remotessh:go_default_library",
"//core/os/file:go_default_library",
"//core/text:go_default_library",
"//gapir/client:go_default_library",
Expand Down
47 changes: 41 additions & 6 deletions cmd/gapis/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ package main
import (
"context"
"flag"
"io"
"os"
"path/filepath"
"sync"
"time"

"google.golang.org/grpc/grpclog"
Expand All @@ -30,6 +33,7 @@ import (
"github.com/google/gapid/core/os/android/adb"
"github.com/google/gapid/core/os/device/bind"
"github.com/google/gapid/core/os/device/host"
"github.com/google/gapid/core/os/device/remotessh"
"github.com/google/gapid/core/os/file"
"github.com/google/gapid/core/text"
"github.com/google/gapid/gapir/client"
Expand All @@ -55,6 +59,7 @@ var (
idleTimeout = flag.Duration("idle-timeout", 0, "_Closes GAPIS if the server is not repeatedly pinged within this duration")
adbPath = flag.String("adb", "", "Path to the adb executable; leave empty to search the environment")
enableLocalFiles = flag.Bool("enable-local-files", false, "Allow clients to access local .gfxtrace files by path")
remoteSSHConfig = flag.String("ssh-config", "", "_Path to an ssh config file for remote devices")
)

func main() {
Expand Down Expand Up @@ -101,13 +106,28 @@ func run(ctx context.Context) error {
r.SetDeviceProperty(ctx, host, client.LaunchArgsKey, text.SplitArgs(*gapirArgStr))
}

deviceScanDone, onDeviceScanDone := task.NewSignal()
wg := sync.WaitGroup{}

if *scanAndroidDevs {
crash.Go(func() { monitorAndroidDevices(ctx, r, onDeviceScanDone) })
} else {
onDeviceScanDone(ctx)
wg.Add(1)
crash.Go(func() { monitorAndroidDevices(ctx, r, wg.Done) })
}

if *remoteSSHConfig != "" {
f, err := os.Open(*remoteSSHConfig)
if err != nil {
return err
}
wg.Add(1)
crash.Go(func() { getRemoteSSHDevices(ctx, r, f, wg.Done) })
}

deviceScanDone, onDeviceScanDone := task.NewSignal()
crash.Go(func() {
wg.Wait()
onDeviceScanDone(ctx)
})

return server.Listen(ctx, *rpc, server.Config{
Info: &service.ServerInfo{
Name: host.Instance(ctx).Name,
Expand All @@ -125,10 +145,10 @@ func run(ctx context.Context) error {
})
}

func monitorAndroidDevices(ctx context.Context, r *bind.Registry, onDeviceScanDone task.Task) {
func monitorAndroidDevices(ctx context.Context, r *bind.Registry, scanDone func()) {
// Populate the registry with all the existing devices.
func() {
defer onDeviceScanDone(ctx) // Signal that we have a primed registry.
defer scanDone() // Signal that we have a primed registry.

if devs, err := adb.Devices(ctx); err == nil {
for _, d := range devs {
Expand All @@ -142,6 +162,21 @@ func monitorAndroidDevices(ctx context.Context, r *bind.Registry, onDeviceScanDo
}
}

func getRemoteSSHDevices(ctx context.Context, r *bind.Registry, f io.Reader, scanDone func()) {
// Populate the registry with all the existing devices.
func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of this func?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function was originally longer, so it was for the defer(), but no longer needed.

defer scanDone() // Signal that we have a primed registry.

if devs, err := remotessh.Devices(ctx, f); err == nil {
for _, d := range devs {
r.AddDevice(ctx, d)
r.SetDeviceProperty(ctx, d, client.LaunchArgsKey, text.SplitArgs(*gapirArgStr))
}
}

}()
}

func loadStrings(ctx context.Context) []*stringtable.StringTable {
files, err := filepath.Glob(filepath.Join(*stringsPath, "*.stb"))
if err != nil {
Expand Down
9 changes: 5 additions & 4 deletions cmd/gapit/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (verb *traceVerb) Run(ctx context.Context, flags flag.FlagSet) error {

if !verb.Local.App.IsEmpty() {
cleanup, err := verb.startLocalApp(ctx)
defer func() { cleanup() }()
defer func() { cleanup(ctx) }()
if err != nil {
return err
}
Expand Down Expand Up @@ -139,12 +139,13 @@ func (verb *traceVerb) inputHandler(ctx context.Context, deferStart bool) (conte
return ctx, startSignal
}

func (verb *traceVerb) startLocalApp(ctx context.Context) (func(), error) {
func (verb *traceVerb) startLocalApp(ctx context.Context) (func(ctx context.Context), error) {
// Run the local application with VK_LAYER_PATH, VK_INSTANCE_LAYERS,
// VK_DEVICE_LAYERS and LD_PRELOAD set to correct values to load the spy
// layer.
env := shell.CloneEnv()
cleanup, portFile, err := loader.SetupTrace(ctx, env)
device := bind.Host(ctx)
cleanup, portFile, err := loader.SetupTrace(ctx, device, device.Instance().Configuration.ABIs[0], env)
if err != nil {
return cleanup, err
}
Expand All @@ -166,7 +167,7 @@ func (verb *traceVerb) startLocalApp(ctx context.Context) (func(), error) {
if verb.Local.Port == 0 {
verb.Local.Port = boundPort
}
return func() { cancel(); cleanup() }, nil
return func(ctx context.Context) { cancel(); cleanup(ctx) }, nil
}

type traceOptions struct {
Expand Down
89 changes: 73 additions & 16 deletions core/app/layout/layout.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,17 @@ type FileLayout interface {
// Gapis returns the path to the gapis binary in this layout.
Gapis(ctx context.Context) (file.Path, error)
// Gapir returns the path to the gapir binary in this layout.
Gapir(ctx context.Context) (file.Path, error)
Gapir(ctx context.Context, abi *device.ABI) (file.Path, error)
// GapidApk returns the path to gapid.apk in this layout.
GapidApk(ctx context.Context, abi *device.ABI) (file.Path, error)
// Library returns the path to the requested library.
Library(ctx context.Context, lib LibraryType) (file.Path, error)
Library(ctx context.Context, lib LibraryType, abi *device.ABI) (file.Path, error)
// Json returns the path to the Vulkan layer JSON definition for the given library.
Json(ctx context.Context, lib LibraryType) (file.Path, error)
// GoArgs returns additional arguments to pass to go binaries.
GoArgs(ctx context.Context) []string
// DeviceInfo returns the device info executable for the given ABI.
DeviceInfo(ctx context.Context, os device.OSKind) (file.Path, error)
}

func withExecutablePlatformSuffix(exe string, os device.OSKind) string {
Expand Down Expand Up @@ -88,6 +90,11 @@ func withLibraryPlatformSuffix(lib string, os device.OSKind) string {
}
}

// GetLibraryName returns the filename of the given Library.
func GetLibraryName(lib LibraryType, abi *device.ABI) string {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: Doc strings everywhere

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: drop Get unless it collides with something else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return withLibraryPlatformSuffix(libTypeToName[lib], abi.OS)
}

var abiToApk = map[device.Architecture]string{
device.ARMv7a: "gapid-armeabi.apk",
device.ARMv8a: "gapid-aarch64.apk",
Expand All @@ -112,8 +119,17 @@ func (l pkgLayout) Gapit(ctx context.Context) (file.Path, error) {
return l.root.Join(withExecutablePlatformSuffix("gapit", hostOS(ctx))), nil
}

func (l pkgLayout) Gapir(ctx context.Context) (file.Path, error) {
return l.root.Join(withExecutablePlatformSuffix("gapir", hostOS(ctx))), nil
var osToDir = map[device.OSKind]string{
device.Linux: "linux",
device.OSX: "macos",
device.Windows: "windows",
}

func (l pkgLayout) Gapir(ctx context.Context, abi *device.ABI) (file.Path, error) {
if hostOS(ctx) == abi.OS {
return l.root.Join(withExecutablePlatformSuffix("gapir", hostOS(ctx))), nil
}
return l.root.Join(osToDir[abi.OS], withExecutablePlatformSuffix("gapir", abi.OS)), nil
}

func (l pkgLayout) Gapis(ctx context.Context) (file.Path, error) {
Expand All @@ -124,8 +140,11 @@ func (l pkgLayout) GapidApk(ctx context.Context, abi *device.ABI) (file.Path, er
return l.root.Join(abiToApk[abi.Architecture]), nil
}

func (l pkgLayout) Library(ctx context.Context, lib LibraryType) (file.Path, error) {
return l.root.Join("lib", withLibraryPlatformSuffix(libTypeToName[lib], hostOS(ctx))), nil
func (l pkgLayout) Library(ctx context.Context, lib LibraryType, abi *device.ABI) (file.Path, error) {
if hostOS(ctx) == abi.OS {
return l.root.Join("lib", withLibraryPlatformSuffix(libTypeToName[lib], hostOS(ctx))), nil
}
return l.root.Join(osToDir[abi.OS], "lib", withLibraryPlatformSuffix(libTypeToName[lib], abi.OS)), nil
}

func (l pkgLayout) Json(ctx context.Context, lib LibraryType) (file.Path, error) {
Expand All @@ -136,6 +155,13 @@ func (l pkgLayout) GoArgs(ctx context.Context) []string {
return nil
}

func (l pkgLayout) DeviceInfo(ctx context.Context, os device.OSKind) (file.Path, error) {
if hostOS(ctx) == os {
return l.root.Join(withExecutablePlatformSuffix("device-info", os)), nil
}
return l.root.Join(osToDir[os], withExecutablePlatformSuffix("device-info", os)), nil
}

// NewPkgLayout returns a FileLayout rooted at the given directory with the standard package layout.
// If create is true, the package layout is created if it doesn't exist, otherwise an error is returned.
func NewPkgLayout(dir file.Path, create bool) (FileLayout, error) {
Expand Down Expand Up @@ -220,16 +246,22 @@ func (l *runfilesLayout) Gapis(ctx context.Context) (file.Path, error) {
return l.find(withExecutablePlatformSuffix("gapid/cmd/gapis/gapis", hostOS(ctx)))
}

func (l *runfilesLayout) Gapir(ctx context.Context) (file.Path, error) {
return l.find(withExecutablePlatformSuffix("gapid/cmd/gapir/cc/gapir", hostOS(ctx)))
func (l *runfilesLayout) Gapir(ctx context.Context, abi *device.ABI) (file.Path, error) {
if hostOS(ctx) == abi.OS {
return l.find(withExecutablePlatformSuffix("gapid/cmd/gapir/cc/gapir", hostOS(ctx)))
}
return file.Path{}, ErrCannotFindPackageFiles
}

func (l *runfilesLayout) GapidApk(ctx context.Context, abi *device.ABI) (file.Path, error) {
return l.find("gapid/gapidapk/android/apk/" + abiToApkPath[abi.Architecture])
}

func (l *runfilesLayout) Library(ctx context.Context, lib LibraryType) (file.Path, error) {
return l.find(withLibraryPlatformSuffix(libTypeToLibPath[lib], hostOS(ctx)))
func (l *runfilesLayout) Library(ctx context.Context, lib LibraryType, abi *device.ABI) (file.Path, error) {
if hostOS(ctx) == abi.OS {
return l.find(withLibraryPlatformSuffix(libTypeToLibPath[lib], hostOS(ctx)))
}
return file.Path{}, ErrCannotFindPackageFiles
}

func (l *runfilesLayout) Json(ctx context.Context, lib LibraryType) (file.Path, error) {
Expand All @@ -240,6 +272,13 @@ func (l *runfilesLayout) GoArgs(ctx context.Context) []string {
return []string{"-runfiles", l.manifest}
}

func (l *runfilesLayout) DeviceInfo(ctx context.Context, os device.OSKind) (file.Path, error) {
if hostOS(ctx) == os {
return l.find("core/os/device/deviceinfo/exe/" + withExecutablePlatformSuffix("device-info", os))
}
return file.Path{}, ErrCannotFindPackageFiles
}

// unknownLayout is the file layout used when no other layout can be discovered.
// All methods will return an error.
type unknownLayout struct{}
Expand All @@ -256,15 +295,15 @@ func (l unknownLayout) Gapis(ctx context.Context) (file.Path, error) {
return file.Path{}, ErrCannotFindPackageFiles
}

func (l unknownLayout) Gapir(ctx context.Context) (file.Path, error) {
func (l unknownLayout) Gapir(ctx context.Context, abi *device.ABI) (file.Path, error) {
return file.Path{}, ErrCannotFindPackageFiles
}

func (l unknownLayout) GapidApk(ctx context.Context, abi *device.ABI) (file.Path, error) {
return file.Path{}, ErrCannotFindPackageFiles
}

func (l unknownLayout) Library(ctx context.Context, lib LibraryType) (file.Path, error) {
func (l unknownLayout) Library(ctx context.Context, lib LibraryType, abi *device.ABI) (file.Path, error) {
return file.Path{}, ErrCannotFindPackageFiles
}

Expand All @@ -276,6 +315,10 @@ func (l unknownLayout) GoArgs(ctx context.Context) []string {
return nil
}

func (l unknownLayout) DeviceInfo(ctx context.Context, os device.OSKind) (file.Path, error) {
return file.Path{}, ErrCannotFindPackageFiles
}

// ZipLayout is a FileLayout view over a ZIP file.
type ZipLayout struct {
f *zip.Reader
Expand Down Expand Up @@ -317,8 +360,11 @@ func (l *ZipLayout) Gapit(ctx context.Context) (*zip.File, error) {
}

// Gapir returns the path to the gapir binary in this layout.
func (l *ZipLayout) Gapir(ctx context.Context) (*zip.File, error) {
return l.file(withExecutablePlatformSuffix("gapir", l.os))
func (l *ZipLayout) Gapir(ctx context.Context, abi *device.ABI) (*zip.File, error) {
if l.os == abi.OS {
return l.file(withExecutablePlatformSuffix("gapir", l.os))
}
return l.file(osToDir[abi.OS] + "/" + withExecutablePlatformSuffix("gapir", abi.OS))
}

// Gapis returns the path to the gapis binary in this layout.
Expand All @@ -332,11 +378,22 @@ func (l *ZipLayout) GapidApk(ctx context.Context, abi *device.ABI) (*zip.File, e
}

// Library returns the path to the requested library.
func (l *ZipLayout) Library(ctx context.Context, lib LibraryType) (*zip.File, error) {
return l.file("lib/" + withLibraryPlatformSuffix(libTypeToName[lib], l.os))
func (l *ZipLayout) Library(ctx context.Context, lib LibraryType, abi *device.ABI) (*zip.File, error) {
if l.os == abi.OS {
return l.file("lib/" + withLibraryPlatformSuffix(libTypeToName[lib], l.os))
}
return l.file(osToDir[abi.OS] + "lib/" + withLibraryPlatformSuffix(libTypeToName[lib], abi.OS))
}

// Json returns the path to the Vulkan layer JSON definition for the given library.
func (l *ZipLayout) Json(ctx context.Context, lib LibraryType) (*zip.File, error) {
return l.file("lib/" + libTypeToJson[lib])
}

// DeviceInfo returns the device info executable for the given ABI.
func (l *ZipLayout) DeviceInfo(ctx context.Context, os device.OSKind) (*zip.File, error) {
if l.os == os {
return l.file(withExecutablePlatformSuffix("device-info", os))
}
return l.file(osToDir[os] + "/" + withExecutablePlatformSuffix("device-info", os))
}
13 changes: 9 additions & 4 deletions core/app/layout/pkgdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ func GapidApk(ctx context.Context, abi *device.ABI) (file.Path, error) {
}

// Gapir returns the path to the gapir binary.
func Gapir(ctx context.Context) (file.Path, error) {
return layout(ctx).Gapir(ctx)
func Gapir(ctx context.Context, abi *device.ABI) (file.Path, error) {
return layout(ctx).Gapir(ctx, abi)
}

// Gapit returns the path to the gapir binary.
Expand All @@ -104,8 +104,8 @@ func Gapit(ctx context.Context) (file.Path, error) {
}

// Library returns the path to the requested library.
func Library(ctx context.Context, lib LibraryType) (file.Path, error) {
return layout(ctx).Library(ctx, lib)
func Library(ctx context.Context, lib LibraryType, abi *device.ABI) (file.Path, error) {
return layout(ctx).Library(ctx, lib, abi)
}

// Json returns the path to the Vulkan layer JSON definition for the given library.
Expand All @@ -117,3 +117,8 @@ func Json(ctx context.Context, lib LibraryType) (file.Path, error) {
func GoArgs(ctx context.Context) []string {
return layout(ctx).GoArgs(ctx)
}

// DeviceInfo returns the device info executable for the given ABI.
func DeviceInfo(ctx context.Context, os device.OSKind) (file.Path, error) {
return layout(ctx).DeviceInfo(ctx, os)
}
Loading