Documentation
¶
Index ¶
- Constants
- type Adb
- func (adb *Adb) AirplaneModeEnabled(ctx context.Context) (bool, error)
- func (adb *Adb) AllowMockLocation(ctx context.Context, packageName string) error
- func (adb *Adb) Bugreport(ctx context.Context, outputPath string) error
- func (adb *Adb) ClearPackageData(ctx context.Context, packageName string) error
- func (adb *Adb) ForceStop(ctx context.Context, packageName string) error
- func (adb *Adb) ForwardAbstract(ctx context.Context, hostPort int, socket string) error
- func (adb *Adb) ForwardAdd(ctx context.Context, hostPort, devicePort int) error
- func (adb *Adb) ForwardRemove(ctx context.Context, hostPort int) error
- func (adb *Adb) GrantPermission(ctx context.Context, packageName, permission string) error
- func (adb *Adb) Install(ctx context.Context, apkPath string) error
- func (adb *Adb) Instrument(ctx context.Context, devicePort int) ([]byte, error)
- func (adb *Adb) KeyboardShown(ctx context.Context) (bool, error)
- func (adb *Adb) Keyevent(ctx context.Context, code string) error
- func (adb *Adb) Kill(ctx context.Context, packageName string) error
- func (adb *Adb) OpenLink(ctx context.Context, link string, forceChrome bool) error
- func (adb *Adb) PutSetting(ctx context.Context, namespace, key, value string) error
- func (adb *Adb) RevokePermission(ctx context.Context, packageName, permission string) error
- func (adb *Adb) RuntimePermissions(ctx context.Context, packageName string) ([]string, error)
- func (adb *Adb) SetAirplaneMode(ctx context.Context, enabled bool) error
- func (adb *Adb) Swipe(ctx context.Context, startX, startY, endX, endY int, durationMillis int64) error
- func (adb *Adb) Uninstall(ctx context.Context, packageName string) error
- type AgentAPKs
- type CommandRunner
- type Device
- type Driver
- func (driver *Driver) AddMedia(ctx context.Context, request device.AddMediaRequest) error
- func (driver *Driver) BackPress(ctx context.Context) error
- func (driver *Driver) Capabilities() device.Capabilities
- func (driver *Driver) ClearAppState(ctx context.Context, request device.AppRequest) error
- func (driver *Driver) ClearKeychain(context.Context) error
- func (driver *Driver) Close(ctx context.Context) error
- func (driver *Driver) CollectCrashArtifacts(context.Context, device.ArtifactRequest) ([]device.Artifact, error)
- func (driver *Driver) ContentDescriptor(ctx context.Context, _ device.ContentDescriptorRequest) (device.TreeNode, error)
- func (driver *Driver) DeviceInfo(ctx context.Context) (device.DeviceInfo, error)
- func (driver *Driver) EraseText(ctx context.Context, request device.EraseTextRequest) error
- func (driver *Driver) HideKeyboard(ctx context.Context) error
- func (driver *Driver) InputText(ctx context.Context, request device.InputTextRequest) error
- func (driver *Driver) IsAirplaneModeEnabled(ctx context.Context) (bool, error)
- func (driver *Driver) IsKeyboardVisible(ctx context.Context, _ device.KeyboardRequest) (bool, error)
- func (driver *Driver) IsShutdown(ctx context.Context) (bool, error)
- func (driver *Driver) KillApp(ctx context.Context, request device.AppRequest) error
- func (driver *Driver) LaunchApp(ctx context.Context, request device.LaunchAppRequest) error
- func (driver *Driver) LongPress(ctx context.Context, request device.LongPressRequest) error
- func (driver *Driver) Name() string
- func (driver *Driver) Open(ctx context.Context) error
- func (driver *Driver) OpenLink(ctx context.Context, request device.OpenLinkRequest) error
- func (driver *Driver) PressKey(ctx context.Context, request device.PressKeyRequest) error
- func (driver *Driver) QueryOnDeviceElements(context.Context, device.QueryRequest) ([]device.TreeNode, error)
- func (driver *Driver) ResetProxy(ctx context.Context) error
- func (driver *Driver) ScrollVertical(ctx context.Context, request device.ScrollVerticalRequest) error
- func (driver *Driver) SetAirplaneMode(ctx context.Context, request device.AirplaneModeRequest) error
- func (driver *Driver) SetAndroidChromeDevToolsEnabled(ctx context.Context, request device.ChromeDevToolsRequest) error
- func (driver *Driver) SetLocation(ctx context.Context, location device.Location) error
- func (driver *Driver) SetOrientation(ctx context.Context, orientation device.Orientation) error
- func (driver *Driver) SetPermissions(ctx context.Context, request device.PermissionsRequest) error
- func (driver *Driver) SetProxy(ctx context.Context, proxy device.Proxy) error
- func (driver *Driver) StartDeviceLogCapture(context.Context, device.DeviceLogRequest) (device.CaptureID, error)
- func (driver *Driver) StartScreenRecording(ctx context.Context, request device.ScreenRecordingRequest) (device.CaptureID, error)
- func (driver *Driver) StopApp(ctx context.Context, request device.AppRequest) error
- func (driver *Driver) StopDeviceLogCapture(context.Context, device.CaptureID) ([]device.Artifact, error)
- func (driver *Driver) StopScreenRecording(ctx context.Context, id device.CaptureID) ([]device.Artifact, error)
- func (driver *Driver) Swipe(ctx context.Context, request device.SwipeRequest) error
- func (driver *Driver) TakeScreenshot(ctx context.Context, _ device.ScreenshotRequest) ([]byte, error)
- func (driver *Driver) Tap(ctx context.Context, request device.TapRequest) error
- func (driver *Driver) WaitForAppToSettle(ctx context.Context, request device.SettleRequest) (*device.ViewHierarchy, error)
- func (driver *Driver) WaitUntilScreenIsStatic(ctx context.Context, _ device.ScreenStaticRequest) (bool, error)
- type ExecRunner
Constants ¶
const ( // AgentAppPackage is the app APK: drivers/android/agent's applicationId. AgentAppPackage = "dev.larchwave.flowbaton" // AgentTestPackage is the instrumentation APK that hosts the gRPC server. AgentTestPackage = "dev.larchwave.flowbaton.test" )
The two installable halves of the on-device agent and the instrumentation entrypoint between them are defined by specs/02-device-drivers.md §2.2.
const Platform = device.Platform("android")
Platform is the device platform this driver reports.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Adb ¶
type Adb struct {
// contains filtered or unexported fields
}
Adb is the typed surface over adb for one device.
func NewAdb ¶
func NewAdb(serial string, runner CommandRunner) *Adb
NewAdb binds a serial to a runner. An empty serial is legal only for the commands that are not device-scoped, such as ListDevices.
func (*Adb) AirplaneModeEnabled ¶
AirplaneModeEnabled reads the state from the connectivity service's own command, which reports exactly "enabled" or "disabled".
func (*Adb) AllowMockLocation ¶
AllowMockLocation lets a package feed the platform a mock location. The agent is an ordinary app, and LocationManager throws MOCK_LOCATION at one that has not been allowed the app-op — which is what setLocation hit on a real emulator.
func (*Adb) Bugreport ¶
Bugreport writes the device's diagnostic bundle to outputPath. adb chooses zip vs flat based on the device's own bugreport support; the path is passed through unchanged.
func (*Adb) ClearPackageData ¶
ClearPackageData is what clearState means on Android: pm clear wipes the app's data and cache without uninstalling it.
func (*Adb) ForwardAbstract ¶
ForwardAbstract publishes an abstract unix socket on a host TCP port. The Chrome DevTools endpoint of a debuggable WebView lives on one of these (spec 02:44), so a TCP-to-TCP forward cannot reach it.
func (*Adb) ForwardAdd ¶
ForwardAdd publishes the on-device agent port on a host port. The forward is the transport the whole gRPC half rides on.
func (*Adb) GrantPermission ¶
func (*Adb) Install ¶
Install replaces an existing install (-r): the agent APKs are reinstalled per session, and a plain install fails on the second one.
func (*Adb) Instrument ¶
Instrument starts the agent's gRPC server and blocks until the instrumentation exits — for a healthy agent that is the rest of the session, so callers run this on its own goroutine. The shell line is specs/02-device-drivers.md §2.2's, with FlowBaton's packages: -w keeps the process attached so its output reports a refusal, and -m is unconditional because the agent's minSdk is 26, the exact API level the spec gates -m on.
func (*Adb) KeyboardShown ¶
KeyboardShown reads the input-method service state; mInputShown is the flag the IME flips while the soft keyboard is on screen.
func (*Adb) Keyevent ¶
Keyevent presses one key. The symbolic KEYCODE_* names are used rather than raw numbers so the argv reads as the operation it performs.
func (*Adb) Kill ¶
Kill sends the system-initiated process death: the public docs pin killApp on Android to exactly `adb shell am kill <package>`, which the tool's own help describes as killing the app's background processes.
func (*Adb) OpenLink ¶
OpenLink fires the VIEW intent. am start may report resolution failures in its output while exiting successfully, so success requires reading both.
func (*Adb) PutSetting ¶
PutSetting writes one settings row; specs/02-device-drivers.md line 46 pins the proxy to `settings put global http_proxy` and orientation to `settings put system user_rotation`.
func (*Adb) RevokePermission ¶
func (*Adb) RuntimePermissions ¶
RuntimePermissions lists the app's own changeable permissions, read off `dumpsys package`. This is what `all` expands to: only what the app requested can be granted, and pm refuses everything else.
func (*Adb) SetAirplaneMode ¶
func (*Adb) Swipe ¶
func (adb *Adb) Swipe(ctx context.Context, startX, startY, endX, endY int, durationMillis int64) error
Swipe drags between two points over a duration; the same verb with zero travel is how a long press is expressed. specs/02-device-drivers.md line 43 pins swipes to `adb shell input swipe`, not the gRPC agent.
type AgentAPKs ¶
AgentAPKs names the two installable halves of the on-device agent: the app APK and the instrumentation APK hosting the gRPC server. Handing them to NewDriver makes Open own the whole spec 02 §2.2 lifecycle — reinstall, `am instrument`, and the 100ms reachability poll; a nil AgentAPKs keeps the operator-started mode, where the agent must already be running.
type CommandRunner ¶
type CommandRunner interface {
Run(ctx context.Context, name string, args ...string) ([]byte, error)
}
CommandRunner executes one external command and returns its combined output.
type Device ¶
Device is one entry of the adb inventory.
func ListDevices ¶
func ListDevices(ctx context.Context, runner CommandRunner) ([]Device, error)
ListDevices returns every device adb can currently use. Entries in any other state (offline, unauthorized) are dropped: they cannot run a flow, so offering them as targets would only defer the failure.
type Driver ¶
type Driver struct {
// contains filtered or unexported fields
}
Driver drives one device or emulator.
func NewDriver ¶
func NewDriver(serial string, hostPort int, runner CommandRunner, apks *AgentAPKs) *Driver
NewDriver binds a device serial and a host port to an adb runner. A nil runner executes adb for real; a nil apks means the agent is already running and Open only forwards and probes.
func (*Driver) AddMedia ¶
AddMedia streams each file to the agent over the service's one client-streaming rpc. Every frame carries the name and extension alongside its payload chunk — the metadata is idempotent, which keeps the agent free of first-frame special cases. One rpc moves one file.
func (*Driver) Capabilities ¶
func (driver *Driver) Capabilities() device.Capabilities
Capabilities declares what this driver refuses. Every false here has a matching ErrUnsupported at call time; preflight reads this so a flow is refused before it runs rather than halfway through.
func (*Driver) ClearAppState ¶
ClearAppState is pm clear: data and cache wiped, app still installed — unlike iOS, Android has the per-app verb, so no uninstall is needed.
func (*Driver) ClearKeychain ¶
ClearKeychain is a documented no-op: the public docs state the command "only applies to iOS and has no effect on Android or Web". There is no keychain here to clear, so the success is vacuous rather than a lie.
func (*Driver) Close ¶
Close undoes what Open did: the connection, the instrumentation and the APKs when Open owned them, and the forward. An operator-started agent is left exactly as it was, for the same reason the iOS driver leaves the simulator running — the state after a failed run is something an operator inspects.
func (*Driver) CollectCrashArtifacts ¶
func (*Driver) ContentDescriptor ¶
func (driver *Driver) ContentDescriptor( ctx context.Context, _ device.ContentDescriptorRequest, ) (device.TreeNode, error)
ContentDescriptor asks the agent for the spec 04 §2 XML and converts it. The rpc takes no parameters: the agent dumps the whole screen, so the app filter and the keyboard exclusion have nothing to carry here.
func (*Driver) DeviceInfo ¶
func (*Driver) HideKeyboard ¶
HideKeyboard is the back key: the public docs record that Android hides the keyboard with "a back button event, ... identical to the back command".
func (*Driver) InputText ¶
InputText goes to the agent because shell `input text` mangles unicode and spaces. The agent commits text in-process to the focused field. AppIDs has nothing to carry: input always targets whatever holds focus.
func (*Driver) IsAirplaneModeEnabled ¶
func (*Driver) IsKeyboardVisible ¶
func (*Driver) IsShutdown ¶
IsShutdown asks the agent, not adb: a device whose agent has died is unusable for a flow even though adb still lists it.
func (*Driver) KillApp ¶
KillApp is the system-initiated process death, distinct from StopApp on this platform: the public docs pin it to `adb shell am kill`.
func (*Driver) LaunchApp ¶
LaunchApp goes through the agent, not adb: only the gRPC route carries the typed extras, and `am start` would need the launch activity resolved by hand. An unknown argument type is refused before anything crosses the wire.
func (*Driver) LongPress ¶
LongPress is a zero-travel `input swipe`: the frozen proto has no long press rpc, and holding one point for the duration is exactly what the swipe verb does when start and end coincide.
func (*Driver) Name ¶
Name identifies the agent this driver talks to, port included, like the iOS driver's ios:UDID:PORT.
func (*Driver) Open ¶
Open publishes the agent port on the host and confirms the agent answers. With APKs it owns the whole spec 02 §2.2 lifecycle: reinstall both halves, start the instrumentation, and poll for reachability. Without them the instrumentation must already be RUNNING for any gRPC call to answer; discovering an absent agent here, with the address in the error, is the difference between a setup failure and a flow failure.
func (*Driver) OpenLink ¶
OpenLink fires the VIEW intent. The only browser choice Android honors is the boolean chrome force (openBrowser); any other named browser is refused rather than silently opened in the default.
func (*Driver) QueryOnDeviceElements ¶
func (driver *Driver) QueryOnDeviceElements( context.Context, device.QueryRequest, ) ([]device.TreeNode, error)
QueryOnDeviceElements has no rpc in the frozen proto: the agent returns a whole hierarchy, it does not evaluate queries against it.
func (*Driver) ResetProxy ¶
ResetProxy writes the sentinel ":0", the platform's own convention for "no proxy" — deleting the row does not reliably clear an applied proxy.
func (*Driver) ScrollVertical ¶
func (driver *Driver) ScrollVertical(ctx context.Context, request device.ScrollVerticalRequest) error
ScrollVertical is a swipe across the middle of the screen, sized from the device's own geometry — the same rule as the iOS driver, on the pixel grid.
func (*Driver) SetAirplaneMode ¶
func (*Driver) SetAndroidChromeDevToolsEnabled ¶
func (driver *Driver) SetAndroidChromeDevToolsEnabled( ctx context.Context, request device.ChromeDevToolsRequest, ) error
SetAndroidChromeDevToolsEnabled turns the WebView merge on or off.
Enabling publishes the device's abstract DevTools socket on a host port and attaches to it; disabling closes the connection and removes the forward. A forward left behind pins its host port for the life of the adb server, so the next shard that reserves that number gets a socket pointing at a dead page.
func (*Driver) SetLocation ¶
SetLocation enables the agent's mock providers first, then pushes the coordinate: setLocation lands on the mock Fused/LocationManager providers, which do not exist until the agent registers them.
func (*Driver) SetOrientation ¶
func (*Driver) SetPermissions ¶
SetPermissions applies one pm call per permission, in a stable order: pm takes a single permission per invocation, and map order must not decide what gets applied first.
`all` is applied before the named keys so an explicit key can override it — the docs' own example is `all: deny` plus `camera: allow`. It expands to the app's OWN runtime permissions (read off dumpsys), because pm refuses to grant anything the app never requested.
ponytail: a named permission the app did not request still fails with pm's own SecurityException naming it; intersecting named keys with the manifest too is the upgrade path if that ever bites.
func (*Driver) StartDeviceLogCapture ¶
func (*Driver) StartScreenRecording ¶
func (driver *Driver) StartScreenRecording( ctx context.Context, request device.ScreenRecordingRequest, ) (device.CaptureID, error)
StartScreenRecording spawns `adb shell screenrecord <devicePath>` as a long-lived child (specs/02-device-drivers.md line 9) and returns a CaptureID that StopScreenRecording later stops. screenrecord can only write to device storage, so it records to /sdcard/<name> and stop pulls the finished file to the host sink.
func (*Driver) StopDeviceLogCapture ¶
func (*Driver) StopScreenRecording ¶
func (driver *Driver) StopScreenRecording( ctx context.Context, id device.CaptureID, ) ([]device.Artifact, error)
StopScreenRecording ends a recording StartScreenRecording began, pulls the artifact to its sink, and returns it. Like the iOS counterpart it is NOT on the frozen Driver surface — v0 declares only the start half — so the recording controller completes the lifecycle by calling this directly.
func (*Driver) Swipe ¶
Swipe covers the three shapes specs/02-device-drivers.md §1 gives the driver, all through `input swipe` (specs/02 line 43): explicit points, a bare direction, and an element point plus a direction.
func (*Driver) TakeScreenshot ¶
func (driver *Driver) TakeScreenshot( ctx context.Context, _ device.ScreenshotRequest, ) ([]byte, error)
TakeScreenshot returns the agent's PNG. The compressed flag is iOS's JPEG-vs-PNG switch; the Android agent produces PNG either way (spec 04 §1), so there is nothing here for the flag to change.
func (*Driver) WaitForAppToSettle ¶
func (driver *Driver) WaitForAppToSettle( ctx context.Context, request device.SettleRequest, ) (*device.ViewHierarchy, error)
WaitForAppToSettle returns nil while the window is still updating. Callers must not interpret nil as settled confirmation.
func (*Driver) WaitUntilScreenIsStatic ¶
func (driver *Driver) WaitUntilScreenIsStatic( ctx context.Context, _ device.ScreenStaticRequest, ) (bool, error)
WaitUntilScreenIsStatic is the inverse of the agent's isWindowUpdating. The timeout is the caller's to enforce: the engine owns every wait budget.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package grpcwire is a minimal gRPC-over-h2c client for the Android agent.
|
Package grpcwire is a minimal gRPC-over-h2c client for the Android agent. |
|
Package pbwire is a hand-rolled proto3 codec for exactly the messages of proto/flowbaton_android.proto.
|
Package pbwire is a hand-rolled proto3 codec for exactly the messages of proto/flowbaton_android.proto. |