# gRPC server API (tap.v1)

Generated from `contracts/proto/*.proto` by protoc-gen-doc. The narrative
contract — run liveness, the pool, sessions, status mapping — is in the repository's
`.docs/server-api.md`.

<a name="app-proto"></a>

## app.proto



<a name="tap-v1-AppTarget"></a>

### AppTarget
The package an App call acts on, on a device the calling connection has attached.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| package_name | [string](#string) |  |  |






<a name="tap-v1-AwaitIdleRequest"></a>

### AwaitIdleRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| timeout_ms | [int64](#int64) | optional |  |
| stable_for_ms | [int64](#int64) | optional | absent = 200 |






<a name="tap-v1-AwaitIdleResponse"></a>

### AwaitIdleResponse







<a name="tap-v1-ClearDataRequest"></a>

### ClearDataRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| timeout_ms | [int64](#int64) | optional |  |






<a name="tap-v1-ClearDataResponse"></a>

### ClearDataResponse







<a name="tap-v1-ColdLaunchRequest"></a>

### ColdLaunchRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| activity | [string](#string) | optional | absent = launcher activity |
| timeout_ms | [int64](#int64) | optional |  |
| extras | [IntentExtra](#tap-v1-IntentExtra) | repeated | as LaunchRequest |






<a name="tap-v1-ColdLaunchResponse"></a>

### ColdLaunchResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| process | [ProcessIdentity](#tap-v1-ProcessIdentity) |  |  |






<a name="tap-v1-ForceStopRequest"></a>

### ForceStopRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| timeout_ms | [int64](#int64) | optional |  |






<a name="tap-v1-ForceStopResponse"></a>

### ForceStopResponse







<a name="tap-v1-ForegroundRequest"></a>

### ForegroundRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| timeout_ms | [int64](#int64) | optional |  |






<a name="tap-v1-ForegroundResponse"></a>

### ForegroundResponse







<a name="tap-v1-GetLocalesRequest"></a>

### GetLocalesRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |






<a name="tap-v1-GetLocalesResponse"></a>

### GetLocalesResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| locales | [string](#string) | repeated |  |






<a name="tap-v1-GrantPermissionRequest"></a>

### GrantPermissionRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| permission | [string](#string) |  |  |






<a name="tap-v1-GrantPermissionResponse"></a>

### GrantPermissionResponse







<a name="tap-v1-InstallHeader"></a>

### InstallHeader



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  | package_name: the package the APK must install as |
| timeout_ms | [int64](#int64) | optional |  |
| size_bytes | [int64](#int64) |  | exact APK size; the upload is rejected on mismatch |






<a name="tap-v1-InstallRequest"></a>

### InstallRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| header | [InstallHeader](#tap-v1-InstallHeader) |  | first message only |
| chunk | [bytes](#bytes) |  | every later message |






<a name="tap-v1-InstallResponse"></a>

### InstallResponse







<a name="tap-v1-IntentExtra"></a>

### IntentExtra
One `am start` extra. `key`: 1..256 chars, no whitespace or control characters.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| key | [string](#string) |  |  |
| string_value | [string](#string) |  | --es (≤ 4096 chars) |
| bool_value | [bool](#bool) |  | --ez |
| int_value | [int32](#int32) |  | --ei |
| long_value | [int64](#int64) |  | --el |
| float_value | [float](#float) |  | --ef (finite) |






<a name="tap-v1-IsInstalledRequest"></a>

### IsInstalledRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |






<a name="tap-v1-IsInstalledResponse"></a>

### IsInstalledResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| installed | [bool](#bool) |  |  |






<a name="tap-v1-IsPermissionGrantedRequest"></a>

### IsPermissionGrantedRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| permission | [string](#string) |  |  |






<a name="tap-v1-IsPermissionGrantedResponse"></a>

### IsPermissionGrantedResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| granted | [bool](#bool) |  |  |






<a name="tap-v1-IsRunningRequest"></a>

### IsRunningRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |






<a name="tap-v1-IsRunningResponse"></a>

### IsRunningResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| running | [bool](#bool) |  |  |






<a name="tap-v1-LaunchRequest"></a>

### LaunchRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| activity | [string](#string) | optional | absent = launcher activity |
| timeout_ms | [int64](#int64) | optional |  |
| extras | [IntentExtra](#tap-v1-IntentExtra) | repeated | ≤ 64, distinct keys |






<a name="tap-v1-LaunchResponse"></a>

### LaunchResponse







<a name="tap-v1-OpenLinkRequest"></a>

### OpenLinkRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| uri | [string](#string) |  | an absolute URI (scheme required); ≤ 2048 chars, no whitespace or control characters |
| any_app | [bool](#bool) |  | false: only the package may handle it (`-p`), so no chooser can appear. true: Android resolves it as a tapped link would — another app, the browser, or a chooser. |
| timeout_ms | [int64](#int64) | optional |  |






<a name="tap-v1-OpenLinkResponse"></a>

### OpenLinkResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| activity | [string](#string) | optional | The activity Android reports it started or delivered the link to (`package/class`); absent when `am start` names none. |






<a name="tap-v1-ProcessIdentity"></a>

### ProcessIdentity
PID plus a start token that changes on every process start.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| pid | [int32](#int32) |  |  |
| start_token | [string](#string) |  |  |






<a name="tap-v1-ProcessRequest"></a>

### ProcessRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| timeout_ms | [int64](#int64) | optional |  |






<a name="tap-v1-ProcessResponse"></a>

### ProcessResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| process | [ProcessIdentity](#tap-v1-ProcessIdentity) |  |  |






<a name="tap-v1-RevokePermissionRequest"></a>

### RevokePermissionRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| permission | [string](#string) |  |  |






<a name="tap-v1-RevokePermissionResponse"></a>

### RevokePermissionResponse







<a name="tap-v1-SetLocalesRequest"></a>

### SetLocalesRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |
| locales | [string](#string) | repeated | At most 16 well-formed, distinct BCP-47 tags (`fr-FR`, `pt-BR`, `zh-Hant-TW`). |






<a name="tap-v1-SetLocalesResponse"></a>

### SetLocalesResponse







<a name="tap-v1-UninstallRequest"></a>

### UninstallRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| app | [AppTarget](#tap-v1-AppTarget) |  |  |






<a name="tap-v1-UninstallResponse"></a>

### UninstallResponse






 

 

 


<a name="tap-v1-AppService"></a>

### AppService


| Method Name | Request Type | Response Type | Description |
| ----------- | ------------ | ------------- | ------------|
| Install | [InstallRequest](#tap-v1-InstallRequest) stream | [InstallResponse](#tap-v1-InstallResponse) | `adb install -r -t` of the uploaded APK, verified. The client streams an InstallHeader first, then the APK bytes in chunks. |
| Uninstall | [UninstallRequest](#tap-v1-UninstallRequest) | [UninstallResponse](#tap-v1-UninstallResponse) | `pm uninstall`, verified. |
| IsInstalled | [IsInstalledRequest](#tap-v1-IsInstalledRequest) | [IsInstalledResponse](#tap-v1-IsInstalledResponse) |  |
| ForceStop | [ForceStopRequest](#tap-v1-ForceStopRequest) | [ForceStopResponse](#tap-v1-ForceStopResponse) | `am force-stop` plus proof that no process and no activity of the package remain. |
| ClearData | [ClearDataRequest](#tap-v1-ClearDataRequest) | [ClearDataResponse](#tap-v1-ClearDataResponse) | `pm clear`; data, cache and runtime permissions gone, app left stopped (no process, no activity). |
| GrantPermission | [GrantPermissionRequest](#tap-v1-GrantPermissionRequest) | [GrantPermissionResponse](#tap-v1-GrantPermissionResponse) | `pm grant` a runtime permission. |
| RevokePermission | [RevokePermissionRequest](#tap-v1-RevokePermissionRequest) | [RevokePermissionResponse](#tap-v1-RevokePermissionResponse) | `pm revoke` a runtime permission, verified like a grant. Android kills the app&#39;s process. |
| IsPermissionGranted | [IsPermissionGrantedRequest](#tap-v1-IsPermissionGrantedRequest) | [IsPermissionGrantedResponse](#tap-v1-IsPermissionGrantedResponse) | Whether `dumpsys package` lists the permission as granted to the package (a read; not logged). |
| SetLocales | [SetLocalesRequest](#tap-v1-SetLocalesRequest) | [SetLocalesResponse](#tap-v1-SetLocalesResponse) | The app&#39;s own languages (`cmd locale set-app-locales`, API 33&#43;; FAILED_PRECONDITION, UNSUPPORTED_API below), BCP-47 tags in preference order; empty = follow the system. Read back after the change; restored on detach like the device conditions. |
| GetLocales | [GetLocalesRequest](#tap-v1-GetLocalesRequest) | [GetLocalesResponse](#tap-v1-GetLocalesResponse) | The app&#39;s own languages now (`cmd locale get-app-locales`); empty = it follows the system. |
| Launch | [LaunchRequest](#tap-v1-LaunchRequest) | [LaunchResponse](#tap-v1-LaunchResponse) | Start the activity (or the launcher) and wait for the package to own the focused window. |
| ColdLaunch | [ColdLaunchRequest](#tap-v1-ColdLaunchRequest) | [ColdLaunchResponse](#tap-v1-ColdLaunchResponse) | Verified force-stop, launch, then a new process identity in the foreground. |
| Foreground | [ForegroundRequest](#tap-v1-ForegroundRequest) | [ForegroundResponse](#tap-v1-ForegroundResponse) | `am start -W` of the launcher intent, as the home screen does: the app&#39;s existing task comes back as it was left; with no task, the launcher activity starts. |
| OpenLink | [OpenLinkRequest](#tap-v1-OpenLinkRequest) | [OpenLinkResponse](#tap-v1-OpenLinkResponse) | `am start -W -a android.intent.action.VIEW -d &lt;uri&gt;`, limited to the package unless `any_app`. |
| Process | [ProcessRequest](#tap-v1-ProcessRequest) | [ProcessResponse](#tap-v1-ProcessResponse) | The single current process identity. |
| IsRunning | [IsRunningRequest](#tap-v1-IsRunningRequest) | [IsRunningResponse](#tap-v1-IsRunningResponse) | Whether any process of the package is alive. |
| AwaitIdle | [AwaitIdleRequest](#tap-v1-AwaitIdleRequest) | [AwaitIdleResponse](#tap-v1-AwaitIdleResponse) | Wait until the app&#39;s sync-sdk busy count is zero and stable for `stable_for_ms`. |

 



<a name="selector-proto"></a>

## selector.proto



<a name="tap-v1-AllOf"></a>

### AllOf
Conjunction: every operand must hold. At least two operands.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| nodes | [Node](#tap-v1-Node) | repeated |  |






<a name="tap-v1-AnyOf"></a>

### AnyOf
Disjunction: at least one operand must hold. At least two operands. Evaluated by the
driver&#39;s traversal plan rather than a native BySelector.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| nodes | [Node](#tap-v1-Node) | repeated |  |






<a name="tap-v1-At"></a>

### At



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| index | [int32](#int32) |  |  |






<a name="tap-v1-ExactlyOne"></a>

### ExactlyOne
Pick variants: exactly one match (default; more is AMBIGUOUS), the first in accessibility
order, or the zero-based `index`-th in accessibility order (NOT_FOUND when absent).






<a name="tap-v1-First"></a>

### First







<a name="tap-v1-Flag"></a>

### Flag
A boolean property that must equal `value`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| property | [NodeFlag](#tap-v1-NodeFlag) |  |  |
| value | [bool](#bool) |  |  |






<a name="tap-v1-Match"></a>

### Match
A string property compared against `value` under `mode`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| property | [TextProperty](#tap-v1-TextProperty) |  |  |
| value | [string](#string) |  |  |
| mode | [MatchMode](#tap-v1-MatchMode) |  |  |






<a name="tap-v1-Node"></a>

### Node
One node predicate of the selector expression tree. Limits over the whole tree: depth ≤ 32,
≤ 256 nodes, strings ≤ 1024 chars.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| match | [Match](#tap-v1-Match) |  |  |
| flag | [Flag](#tap-v1-Flag) |  |  |
| resource | [ResourceId](#tap-v1-ResourceId) |  |  |
| related | [Related](#tap-v1-Related) |  |  |
| all_of | [AllOf](#tap-v1-AllOf) |  |  |
| any_of | [AnyOf](#tap-v1-AnyOf) |  |  |






<a name="tap-v1-Related"></a>

### Related
The `relation` of the node must satisfy `node`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| relation | [Relation](#tap-v1-Relation) |  |  |
| node | [Node](#tap-v1-Node) |  |  |






<a name="tap-v1-ResourceId"></a>

### ResourceId
A View resource id. With `package_name`: exactly `package_name:id/name`. Without: `name` in any
package (`&lt;any&gt;:id/name`) or the bare `name`, which is how a Compose testTag appears under
testTagsAsResourceId. `name` never contains `:id/`; put the package in `package_name`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| name | [string](#string) |  |  |
| package_name | [string](#string) | optional |  |






<a name="tap-v1-Selector"></a>

### Selector
A complete selector: the node tree and how an action picks among matches. Package ownership
is an ordinary PROPERTY_PACKAGE_NAME predicate; there is no separate execution scope.
Built by the client DSLs and validated identically by the server and the driver.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| node | [Node](#tap-v1-Node) |  |  |
| exactly_one | [ExactlyOne](#tap-v1-ExactlyOne) |  |  |
| first | [First](#tap-v1-First) |  |  |
| at | [At](#tap-v1-At) |  |  |





 


<a name="tap-v1-MatchMode"></a>

### MatchMode
How a Match compares; REGEX is RE2 syntax, full match.

| Name | Number | Description |
| ---- | ------ | ----------- |
| MATCH_UNSPECIFIED | 0 | = MATCH_EXACT |
| MATCH_EXACT | 1 |  |
| MATCH_CONTAINS | 2 |  |
| MATCH_STARTS_WITH | 3 |  |
| MATCH_ENDS_WITH | 4 |  |
| MATCH_REGEX | 5 |  |



<a name="tap-v1-NodeFlag"></a>

### NodeFlag
The boolean node properties a Flag can constrain.

| Name | Number | Description |
| ---- | ------ | ----------- |
| FLAG_UNSPECIFIED | 0 | rejected |
| FLAG_ENABLED | 1 |  |
| FLAG_CHECKED | 2 |  |
| FLAG_CHECKABLE | 3 |  |
| FLAG_CLICKABLE | 4 |  |
| FLAG_FOCUSED | 5 |  |
| FLAG_FOCUSABLE | 6 |  |
| FLAG_LONG_CLICKABLE | 7 |  |
| FLAG_SCROLLABLE | 8 |  |
| FLAG_SELECTED | 9 |  |



<a name="tap-v1-Relation"></a>

### Relation
Which relative a Related constrains.

| Name | Number | Description |
| ---- | ------ | ----------- |
| RELATION_UNSPECIFIED | 0 | rejected |
| RELATION_PARENT | 1 | the direct parent matches |
| RELATION_ANCESTOR | 2 | some ancestor matches |
| RELATION_CHILD | 3 | at least one direct child matches |
| RELATION_DESCENDANT | 4 | at least one descendant matches |



<a name="tap-v1-TextProperty"></a>

### TextProperty
The string-valued node properties a Match can constrain.

| Name | Number | Description |
| ---- | ------ | ----------- |
| PROPERTY_UNSPECIFIED | 0 | rejected |
| PROPERTY_TEXT | 1 |  |
| PROPERTY_CONTENT_DESCRIPTION | 2 |  |
| PROPERTY_HINT | 3 |  |
| PROPERTY_CLASS_NAME | 4 |  |
| PROPERTY_PACKAGE_NAME | 5 |  |


 

 

 



<a name="command-proto"></a>

## command.proto



<a name="tap-v1-AwaitNotification"></a>

### AwaitNotification
Waits until a matching notification is active (one already posted counts) and returns the
newest; WAIT_TIMEOUT (NO_NOTIFICATION) otherwise. No input.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| match | [NotificationMatch](#tap-v1-NotificationMatch) |  |  |






<a name="tap-v1-AwaitToast"></a>

### AwaitToast
Waits for a toast. `text` (≤ 1024 chars) is compared under `mode` (default exact); absent =
any text. `package_name` absent = a toast from any package. A toast posted up to 3.5 s before
the command (the longest one stays up) counts.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| text | [string](#string) | optional |  |
| mode | [MatchMode](#tap-v1-MatchMode) |  |  |
| package_name | [string](#string) | optional |  |






<a name="tap-v1-Bounds"></a>

### Bounds
Screen-pixel rectangle.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| left | [int32](#int32) |  |  |
| top | [int32](#int32) |  |  |
| right | [int32](#int32) |  |  |
| bottom | [int32](#int32) |  |  |






<a name="tap-v1-ChoosePermission"></a>

### ChoosePermission
Taps the dialog&#39;s button for `choice`; it must be offered, exactly once.
With `accuracy`, the dialog&#39;s radio for it is selected first; it must be offered too (both are
found before any input). UNSPECIFIED leaves the accuracy as the dialog shows it.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| choice | [PermissionChoice](#tap-v1-PermissionChoice) |  | not UNSPECIFIED |
| accuracy | [LocationAccuracy](#tap-v1-LocationAccuracy) |  |  |






<a name="tap-v1-ClearText"></a>

### ClearText



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-Command"></a>

### Command
One protocol request minus session identity (the server owns session id, generation and
request ids). Exactly one `op` must be set; its case name is the protocol `op`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| timeout_ms | [int64](#int64) | optional | absent = the attached device&#39;s default action timeout |
| device_info | [DeviceInfoQuery](#tap-v1-DeviceInfoQuery) |  |  |
| press_key | [PressKey](#tap-v1-PressKey) |  |  |
| dump_hierarchy | [DumpHierarchy](#tap-v1-DumpHierarchy) |  |  |
| exists | [Exists](#tap-v1-Exists) |  |  |
| count | [Count](#tap-v1-Count) |  |  |
| snapshot | [Snapshot](#tap-v1-Snapshot) |  |  |
| wait_visible | [WaitVisible](#tap-v1-WaitVisible) |  |  |
| wait_gone | [WaitGone](#tap-v1-WaitGone) |  |  |
| wait_app_visible | [WaitAppVisible](#tap-v1-WaitAppVisible) |  |  |
| wait_screen_stable | [WaitScreenStable](#tap-v1-WaitScreenStable) |  |  |
| tap | [Tap](#tap-v1-Tap) |  |  |
| long_tap | [LongTap](#tap-v1-LongTap) |  |  |
| set_text | [SetText](#tap-v1-SetText) |  |  |
| type_text | [TypeText](#tap-v1-TypeText) |  |  |
| clear_text | [ClearText](#tap-v1-ClearText) |  |  |
| swipe | [Swipe](#tap-v1-Swipe) |  |  |
| scroll | [Scroll](#tap-v1-Scroll) |  |  |
| open_system_panel | [OpenSystemPanel](#tap-v1-OpenSystemPanel) |  |  |
| set_orientation | [SetOrientation](#tap-v1-SetOrientation) |  |  |
| set_display_rotation | [SetDisplayRotation](#tap-v1-SetDisplayRotation) |  |  |
| unfreeze_rotation | [UnfreezeRotation](#tap-v1-UnfreezeRotation) |  |  |
| dismiss_keyguard | [DismissKeyguard](#tap-v1-DismissKeyguard) |  |  |
| double_tap | [DoubleTap](#tap-v1-DoubleTap) |  |  |
| drag | [Drag](#tap-v1-Drag) |  |  |
| pinch | [Pinch](#tap-v1-Pinch) |  |  |
| fling | [Fling](#tap-v1-Fling) |  |  |
| wait_permission_prompt | [WaitPermissionPrompt](#tap-v1-WaitPermissionPrompt) |  |  |
| choose_permission | [ChoosePermission](#tap-v1-ChoosePermission) |  |  |
| hide_keyboard | [HideKeyboard](#tap-v1-HideKeyboard) |  |  |
| perform_ime_action | [PerformImeAction](#tap-v1-PerformImeAction) |  |  |
| set_clipboard | [SetClipboard](#tap-v1-SetClipboard) |  |  |
| get_clipboard | [GetClipboard](#tap-v1-GetClipboard) |  |  |
| await_toast | [AwaitToast](#tap-v1-AwaitToast) |  |  |
| perform_accessibility_action | [PerformAccessibilityAction](#tap-v1-PerformAccessibilityAction) |  |  |
| set_progress | [SetProgress](#tap-v1-SetProgress) |  |  |
| set_location | [SetLocation](#tap-v1-SetLocation) |  |  |
| await_notification | [AwaitNotification](#tap-v1-AwaitNotification) |  |  |
| list_notifications | [ListNotifications](#tap-v1-ListNotifications) |  |  |
| open_notification | [OpenNotification](#tap-v1-OpenNotification) |  |  |
| dismiss_notification | [DismissNotification](#tap-v1-DismissNotification) |  |  |






<a name="tap-v1-CommandResult"></a>

### CommandResult
One protocol response: exactly one `outcome`, named like the protocol result `kind`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| duration_ms | [int64](#int64) |  |  |
| request_id | [int64](#int64) |  | Identity of the protocol request the server issued, for diagnostics. |
| session_generation | [int64](#int64) |  |  |
| done | [Done](#tap-v1-Done) |  |  |
| bool | [bool](#bool) |  | exists |
| count | [int32](#int32) |  | count, capped at 1000 |
| text | [string](#string) |  | dump_hierarchy, get_clipboard |
| snapshot | [ElementSnapshot](#tap-v1-ElementSnapshot) |  |  |
| device_info | [DeviceInfo](#tap-v1-DeviceInfo) |  |  |
| error | [Error](#tap-v1-Error) |  |  |
| permission_prompt | [PermissionPrompt](#tap-v1-PermissionPrompt) |  |  |
| toast | [Toast](#tap-v1-Toast) |  |  |
| notification | [DeviceNotification](#tap-v1-DeviceNotification) |  | await_notification |
| notifications | [NotificationList](#tap-v1-NotificationList) |  | list_notifications |






<a name="tap-v1-Count"></a>

### Count



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-DeviceInfo"></a>

### DeviceInfo
Static facts about the device plus the package currently owning the focused window.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| api_level | [int32](#int32) |  |  |
| manufacturer | [string](#string) |  |  |
| model | [string](#string) |  |  |
| product | [string](#string) |  |  |
| display_width | [int32](#int32) |  |  |
| display_height | [int32](#int32) |  |  |
| display_rotation | [int32](#int32) |  |  |
| current_package | [string](#string) | optional |  |
| screen_on | [bool](#bool) |  | PowerManager.isInteractive |
| keyguard_locked | [bool](#bool) |  | KeyguardManager.isKeyguardLocked |
| keyguard_secure | [bool](#bool) |  | a PIN, pattern or password is set |
| keyboard_shown | [bool](#bool) |  | an input-method window is on screen |
| auto_rotate | [bool](#bool) |  | Settings.System.ACCELEROMETER_ROTATION: the sensor picks the rotation |
| animations_enabled | [bool](#bool) |  | any of the three animation scales is not 0 |
| dark_mode | [bool](#bool) |  | the current configuration is night (UI_MODE_NIGHT_YES) |
| font_scale | [float](#float) |  | Configuration.fontScale |
| density_dpi | [int32](#int32) |  | Configuration.densityDpi |
| airplane_mode | [bool](#bool) |  | Settings.Global.AIRPLANE_MODE_ON |
| wifi_enabled | [bool](#bool) |  | Settings.Global.WIFI_ON is 1, or 2 (on under airplane mode) |
| mobile_data_enabled | [bool](#bool) |  | Settings.Global `mobile_data`; false without telephony |
| system_locales | [string](#string) | repeated | the system configuration&#39;s LocaleList, as BCP-47 tags |
| stay_awake | [bool](#bool) |  | Settings.Global.STAY_ON_WHILE_PLUGGED_IN is not 0 |
| high_contrast_text | [bool](#bool) | optional | Settings.Secure `high_text_contrast_enabled` / `accessibility_display_inversion_enabled`; absent when Android does not let the driver read them. |
| color_inversion | [bool](#bool) | optional |  |
| bold_text | [bool](#bool) |  | Configuration.fontWeightAdjustment &gt; 0 (API 31&#43;; false below) |






<a name="tap-v1-DeviceInfoQuery"></a>

### DeviceInfoQuery







<a name="tap-v1-DeviceNotification"></a>

### DeviceNotification
An active notification: the package that posted it, its title and text (Notification extras
`android.title` / `android.text`, absent when it has none), the titles of its action buttons,
whether a swipe can dismiss it, and when it was posted (wall clock, epoch milliseconds).


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| package_name | [string](#string) |  |  |
| title | [string](#string) | optional |  |
| text | [string](#string) | optional |  |
| actions | [string](#string) | repeated |  |
| clearable | [bool](#bool) |  |  |
| posted_at_ms | [int64](#int64) |  |  |






<a name="tap-v1-DismissKeyguard"></a>

### DismissKeyguard
Dismisses a keyguard that has no PIN, pattern or password; a secure one is refused, never unlocked.






<a name="tap-v1-DismissNotification"></a>

### DismissNotification
Dismisses the one matching notification as a swipe does. NOT_FOUND / AMBIGUOUS, or
ACTION_REJECTED (NOT_CLEARABLE) for an ongoing one, before anything changes.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| match | [NotificationMatch](#tap-v1-NotificationMatch) |  |  |






<a name="tap-v1-Done"></a>

### Done
The command ran to completion and has nothing else to report.






<a name="tap-v1-DoubleTap"></a>

### DoubleTap
Two taps on the element&#39;s visible centre within Android&#39;s double-tap window, as one gesture.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-Drag"></a>

### Drag
Press and hold on `selector`&#39;s centre until it becomes a long press, move to `target`&#39;s centre,
hold there, release: one gesture. Both resolve to exactly one element before input starts.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| target | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-DumpHierarchy"></a>

### DumpHierarchy







<a name="tap-v1-ElementSnapshot"></a>

### ElementSnapshot
State of one matched node at the instant of `snapshot`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| class_name | [string](#string) | optional |  |
| package_name | [string](#string) | optional |  |
| resource_name | [string](#string) | optional |  |
| text | [string](#string) | optional |  |
| content_description | [string](#string) | optional |  |
| hint | [string](#string) | optional |  |
| bounds | [Bounds](#tap-v1-Bounds) |  |  |
| checkable | [bool](#bool) |  |  |
| checked | [bool](#bool) |  |  |
| clickable | [bool](#bool) |  |  |
| enabled | [bool](#bool) |  |  |
| focusable | [bool](#bool) |  |  |
| focused | [bool](#bool) |  |  |
| long_clickable | [bool](#bool) |  |  |
| scrollable | [bool](#bool) |  |  |
| selected | [bool](#bool) |  |  |
| child_count | [int32](#int32) |  |  |
| showing_hint | [bool](#bool) |  | The node is showing its hint: on API 26&#43; an empty field then reports the hint as `text`. `text` is always the raw accessibility text; selectors match that same raw text. |
| actions | [StandardAction](#tap-v1-StandardAction) | repeated | The standard actions (of StandardAction) and the custom actions (by label) the node offers. |
| custom_actions | [string](#string) | repeated |  |
| range | [Range](#tap-v1-Range) | optional | A range node&#39;s (SeekBar, Slider, RatingBar, ProgressBar) RangeInfo. |






<a name="tap-v1-Error"></a>

### Error
A failed command. Driver-side failures and driver-transport loss are data (including
TRANSPORT_LOST / INDETERMINATE with `detail` = transmission state), never a gRPC error:
gRPC status codes are reserved for the client↔server call itself.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| code | [ErrorCode](#tap-v1-ErrorCode) |  |  |
| detail | [string](#string) | optional | stable sub-reason; see the errors guide |
| message | [string](#string) | optional | human-readable context; never branch on it |
| match_count | [int32](#int32) | optional | WAIT_TIMEOUT of wait_visible / wait_gone: matches at the last poll (capped at 1000). |






<a name="tap-v1-Exists"></a>

### Exists



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-Fling"></a>

### Fling
A fast swipe across the element. `direction` is the content edge moved towards, as for `scroll`.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| direction | [Direction](#tap-v1-Direction) |  |  |






<a name="tap-v1-GetClipboard"></a>

### GetClipboard
Reads the primary clip as plain text (`text` result; &#34;&#34; when the clipboard is empty).






<a name="tap-v1-HideKeyboard"></a>

### HideKeyboard
Hides the on-screen keyboard: one Back key when an input-method window is showing, nothing
otherwise.






<a name="tap-v1-ListNotifications"></a>

### ListNotifications
The active notifications, newest first. No input.






<a name="tap-v1-LongTap"></a>

### LongTap



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-NotificationList"></a>

### NotificationList



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| notifications | [DeviceNotification](#tap-v1-DeviceNotification) | repeated |  |






<a name="tap-v1-NotificationMatch"></a>

### NotificationMatch
Which notifications a notification op means; every field given must match (none: any).
`package_name` exactly; `title` and `text` (≤ 1024 chars each) under `mode` (default exact).
The notifications are what a NotificationListenerService in the driver app sees: the server
gives the driver notification access (`cmd notification allow_listener`) before the first
notification op and takes it back on detach. Group summaries are left out.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| package_name | [string](#string) | optional |  |
| title | [string](#string) | optional |  |
| text | [string](#string) | optional |  |
| mode | [MatchMode](#tap-v1-MatchMode) |  |  |






<a name="tap-v1-OpenNotification"></a>

### OpenNotification
Opens the one matching notification as a tap on it in the shade does: sends its content
intent and, when it auto-cancels, removes it. With `action` (≤ 1024 chars), sends the intent
of its action button with exactly that title instead, and the notification stays. NOT_FOUND /
AMBIGUOUS, or ACTION_REJECTED (ACTION_NOT_OFFERED) when it has no content intent or no such
action, before anything is sent.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| match | [NotificationMatch](#tap-v1-NotificationMatch) |  |  |
| action | [string](#string) | optional |  |






<a name="tap-v1-OpenSystemPanel"></a>

### OpenSystemPanel
Opens `panel` (the accessibility global action); no target. Back or Home close it.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| panel | [SystemPanel](#tap-v1-SystemPanel) |  |  |






<a name="tap-v1-PerformAccessibilityAction"></a>

### PerformAccessibilityAction
An accessibility action on the one matching node, as a screen reader performs it (no touch,
so no occlusion check): a standard action, or a custom one by its exact label (≤ 1024 chars).
The node must offer it: ACTION_REJECTED (ACTION_NOT_OFFERED) before input otherwise.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| standard | [StandardAction](#tap-v1-StandardAction) |  | not UNSPECIFIED |
| custom | [string](#string) |  |  |






<a name="tap-v1-PerformImeAction"></a>

### PerformImeAction
The keyboard&#39;s action key (Search, Go, Done, …) on the field: `ACTION_IME_ENTER`, API 30&#43;.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-PermissionPrompt"></a>

### PermissionPrompt
The runtime-permission dialog on screen: the package of its window (what a selector&#39;s package
scope names; Google builds rename the controller, so it differs from the resource ids&#39; package)
and the choices it offers, in PermissionChoice order.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| package_name | [string](#string) |  |  |
| choices | [PermissionChoice](#tap-v1-PermissionChoice) | repeated |  |
| accuracies | [LocationAccuracy](#tap-v1-LocationAccuracy) | repeated | The location accuracies the dialog offers to pick (empty when it asks for none). |






<a name="tap-v1-Pinch"></a>

### Pinch
Two fingers across the element&#39;s bounds, moving `percent` of its size (1..100; default 80).


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| direction | [PinchDirection](#tap-v1-PinchDirection) |  |  |
| percent | [int32](#int32) | optional |  |






<a name="tap-v1-PressKey"></a>

### PressKey



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| key_code | [int32](#int32) |  |  |






<a name="tap-v1-Range"></a>

### Range



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| type | [RangeType](#tap-v1-RangeType) |  |  |
| min | [float](#float) |  |  |
| max | [float](#float) |  |  |
| current | [float](#float) |  |  |






<a name="tap-v1-Scroll"></a>

### Scroll



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| direction | [Direction](#tap-v1-Direction) |  |  |
| distance_percent | [int32](#int32) | optional | 1..100; default 80 |






<a name="tap-v1-SetClipboard"></a>

### SetClipboard
Replaces the primary clip with plain `text` (≤ 4096 chars).


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| text | [string](#string) |  |  |






<a name="tap-v1-SetDisplayRotation"></a>

### SetDisplayRotation



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| rotation | [DisplayRotation](#tap-v1-DisplayRotation) |  |  |






<a name="tap-v1-SetLocation"></a>

### SetLocation
Mock location: the gps and network providers (and fused, API 31&#43;) report this fix, as
LocationManager test providers the driver owns, sent again every second until the driver
stops or the next set_location. `latitude` -90..90, `longitude` -180..180, `accuracy_m` &gt; 0
(default 5 m), `altitude_m` absent = no altitude. The driver app needs the mock-location app-op
(the host&#39;s DeviceService.SetLocation grants it first); without it Android refuses
(ERR_ACTION_REJECTED).


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| latitude | [double](#double) |  |  |
| longitude | [double](#double) |  |  |
| accuracy_m | [float](#float) | optional |  |
| altitude_m | [double](#double) | optional |  |






<a name="tap-v1-SetOrientation"></a>

### SetOrientation
Sets portable geometry or an exact natural-relative rotation and freezes sensor rotation.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| orientation | [Orientation](#tap-v1-Orientation) |  |  |






<a name="tap-v1-SetProgress"></a>

### SetProgress
`ACTION_SET_PROGRESS` on the one matching range node (SeekBar, Slider, RatingBar): `value` in
the node&#39;s own RangeInfo units, finite and within its min..max. A node without the action or
a value outside the range is ACTION_REJECTED (ACTION_NOT_OFFERED / OUT_OF_RANGE) before input.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| value | [float](#float) |  |  |






<a name="tap-v1-SetText"></a>

### SetText



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| text | [string](#string) |  |  |






<a name="tap-v1-Snapshot"></a>

### Snapshot



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-Swipe"></a>

### Swipe



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| direction | [Direction](#tap-v1-Direction) |  |  |
| distance_percent | [int32](#int32) | optional | 1..100; default 80 |






<a name="tap-v1-Tap"></a>

### Tap



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-Toast"></a>

### Toast
A toast `await_toast` matched: its text and the package that posted it.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| text | [string](#string) |  |  |
| package_name | [string](#string) |  |  |






<a name="tap-v1-TypeText"></a>

### TypeText
Key events for `text` (≤ 256 chars) into whatever has input focus; no target, no click.
Clients tap the field first (the SDKs&#39; element typeText does).


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| text | [string](#string) |  |  |






<a name="tap-v1-UnfreezeRotation"></a>

### UnfreezeRotation
Releases the sensor lock without selecting a new rotation.






<a name="tap-v1-WaitAppVisible"></a>

### WaitAppVisible



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| package_name | [string](#string) |  |  |






<a name="tap-v1-WaitGone"></a>

### WaitGone



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |






<a name="tap-v1-WaitPermissionPrompt"></a>

### WaitPermissionPrompt
Waits for a runtime-permission dialog and reports the choices it offers. No input.






<a name="tap-v1-WaitScreenStable"></a>

### WaitScreenStable



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| package_name | [string](#string) |  |  |
| stable_for_ms | [int64](#int64) | optional | quiet period, 1..30000; default 500 |
| signal | [StabilitySignal](#tap-v1-StabilitySignal) |  | UNSPECIFIED = ALL |






<a name="tap-v1-WaitVisible"></a>

### WaitVisible



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| exactly_one | [bool](#bool) |  | true = wait for exactly one match (a mutation&#39;s precondition); false = one or more. |





 


<a name="tap-v1-Direction"></a>

### Direction
Gesture direction: where the finger moves for `swipe`, the content edge scrolled towards for
`scroll` (DOWN reveals content below).

| Name | Number | Description |
| ---- | ------ | ----------- |
| DIR_UNSPECIFIED | 0 |  |
| DIR_UP | 1 |  |
| DIR_DOWN | 2 |  |
| DIR_LEFT | 3 |  |
| DIR_RIGHT | 4 |  |



<a name="tap-v1-DisplayRotation"></a>

### DisplayRotation
Exact clockwise display rotation relative to the device&#39;s natural orientation.

| Name | Number | Description |
| ---- | ------ | ----------- |
| DISPLAY_ROTATION_UNSPECIFIED | 0 |  |
| DISPLAY_ROTATION_NATURAL | 1 |  |
| DISPLAY_ROTATION_LEFT | 2 |  |
| DISPLAY_ROTATION_UPSIDE_DOWN | 3 |  |
| DISPLAY_ROTATION_RIGHT | 4 |  |



<a name="tap-v1-ErrorCode"></a>

### ErrorCode
Closed error taxonomy shared with the device protocol; `Error.detail` refines it with a
stable sub-reason. See the errors guide for meaning, mutation risk and retryability.

| Name | Number | Description |
| ---- | ------ | ----------- |
| ERR_UNSPECIFIED | 0 |  |
| ERR_INVALID_REQUEST | 1 |  |
| ERR_INVALID_SELECTOR | 2 |  |
| ERR_UNSUPPORTED | 3 |  |
| ERR_UNAUTHENTICATED | 4 |  |
| ERR_SESSION_MISMATCH | 5 |  |
| ERR_DUPLICATE_OR_STALE | 6 |  |
| ERR_OVERLOADED | 7 |  |
| ERR_AUT_MISMATCH | 8 |  |
| ERR_NOT_FOUND | 9 |  |
| ERR_AMBIGUOUS | 10 |  |
| ERR_NOT_INTERACTABLE | 11 |  |
| ERR_STALE_DURING_COMMAND | 12 |  |
| ERR_ACTION_REJECTED | 13 |  |
| ERR_WAIT_TIMEOUT | 14 |  |
| ERR_CANCELLED | 15 |  |
| ERR_DEADLINE_EXCEEDED | 16 |  |
| ERR_AUT_NOT_INSTALLED | 17 |  |
| ERR_AUT_CRASHED | 18 |  |
| ERR_AUT_ANR | 19 |  |
| ERR_SYNC_PROVIDER_UNAVAILABLE | 20 |  |
| ERR_DRIVER_UNHEALTHY | 21 |  |
| ERR_TRANSPORT_LOST | 22 |  |
| ERR_INDETERMINATE | 23 |  |
| ERR_ARTIFACT_TRANSFER_FAILED | 24 |  |
| ERR_PAYLOAD_TOO_LARGE | 25 |  |
| ERR_INTERNAL | 26 |  |
| ERR_UNKNOWN | 27 |  |
| ERR_STALE_BEFORE_INPUT | 28 | The resolved node went stale (its view was detached or replaced) before any input was sent. |



<a name="tap-v1-LocationAccuracy"></a>

### LocationAccuracy
The Precise / Approximate radio buttons of the location dialog (API 31&#43;, when the app asks for
fine location).

| Name | Number | Description |
| ---- | ------ | ----------- |
| LOCATION_ACCURACY_UNSPECIFIED | 0 |  |
| LOCATION_PRECISE | 1 |  |
| LOCATION_APPROXIMATE | 2 |  |



<a name="tap-v1-Orientation"></a>

### Orientation
Portable geometry, independent of the device&#39;s natural orientation.

| Name | Number | Description |
| ---- | ------ | ----------- |
| ORIENTATION_UNSPECIFIED | 0 |  |
| ORIENTATION_PORTRAIT | 1 |  |
| ORIENTATION_LANDSCAPE | 2 |  |



<a name="tap-v1-PermissionChoice"></a>

### PermissionChoice
A button of the runtime-permission dialog, by what it grants. Which ones a dialog offers depends
on the permission, the Android version and the controller build (`wait_permission_prompt`).

| Name | Number | Description |
| ---- | ------ | ----------- |
| PERMISSION_CHOICE_UNSPECIFIED | 0 |  |
| PERMISSION_ALLOW | 1 | &#34;Allow&#34; |
| PERMISSION_ALLOW_FOREGROUND_ONLY | 2 | &#34;While using the app&#34; |
| PERMISSION_ALLOW_ONE_TIME | 3 | &#34;Only this time&#34; |
| PERMISSION_ALLOW_ALWAYS | 4 | &#34;Allow all the time&#34; (API 29 background location) |
| PERMISSION_ALLOW_SELECTED | 5 | &#34;Select photos and videos&#34; (API 34 partial media access) |
| PERMISSION_ALLOW_ALL | 6 | &#34;Allow all&#34; (API 34 media) |
| PERMISSION_DENY | 7 | &#34;Don&#39;t allow&#34; / &#34;Deny&#34; |
| PERMISSION_DENY_AND_DONT_ASK_AGAIN | 8 | &#34;Deny &amp; don&#39;t ask again&#34; |
| PERMISSION_KEEP_FOREGROUND_ONLY | 9 | &#34;Keep while app is in use&#34; (an upgrade request refused) |
| PERMISSION_KEEP_ONE_TIME | 10 | &#34;Keep only this time&#34; (an upgrade request refused) |



<a name="tap-v1-PinchDirection"></a>

### PinchDirection
Opposite finger movements for `pinch`: OPEN spreads two fingers apart (zoom in), CLOSE brings
them together (zoom out).

| Name | Number | Description |
| ---- | ------ | ----------- |
| PINCH_UNSPECIFIED | 0 |  |
| PINCH_OPEN | 1 |  |
| PINCH_CLOSE | 2 |  |



<a name="tap-v1-RangeType"></a>

### RangeType
How a range node counts (`AccessibilityNodeInfo.RangeInfo`).

| Name | Number | Description |
| ---- | ------ | ----------- |
| RANGE_TYPE_UNSPECIFIED | 0 |  |
| RANGE_INT | 1 |  |
| RANGE_FLOAT | 2 |  |
| RANGE_PERCENT | 3 |  |



<a name="tap-v1-StabilitySignal"></a>

### StabilitySignal
What `wait_screen_stable` watches: the accessibility tree, the screen pixels, or both.

| Name | Number | Description |
| ---- | ------ | ----------- |
| STABILITY_UNSPECIFIED | 0 | = STABILITY_ALL |
| STABILITY_TREE | 1 |  |
| STABILITY_PIXELS | 2 |  |
| STABILITY_ALL | 3 |  |



<a name="tap-v1-StandardAction"></a>

### StandardAction
A standard accessibility action that takes no arguments (`AccessibilityNodeInfo.AccessibilityAction`),
as a screen reader performs it. Click and long click are not here: `tap` / `long_tap` touch.

| Name | Number | Description |
| ---- | ------ | ----------- |
| STANDARD_ACTION_UNSPECIFIED | 0 |  |
| A11Y_EXPAND | 1 |  |
| A11Y_COLLAPSE | 2 |  |
| A11Y_DISMISS | 3 |  |
| A11Y_SCROLL_FORWARD | 4 |  |
| A11Y_SCROLL_BACKWARD | 5 |  |
| A11Y_SCROLL_UP | 6 |  |
| A11Y_SCROLL_DOWN | 7 |  |
| A11Y_SCROLL_LEFT | 8 |  |
| A11Y_SCROLL_RIGHT | 9 |  |
| A11Y_PAGE_UP | 10 | API 29&#43; |
| A11Y_PAGE_DOWN | 11 | API 29&#43; |
| A11Y_PAGE_LEFT | 12 | API 29&#43; |
| A11Y_PAGE_RIGHT | 13 | API 29&#43; |
| A11Y_SHOW_ON_SCREEN | 14 |  |
| A11Y_CONTEXT_CLICK | 15 |  |
| A11Y_PRESS_AND_HOLD | 16 | API 30&#43; |
| A11Y_SELECT | 17 |  |
| A11Y_CLEAR_SELECTION | 18 |  |
| A11Y_FOCUS | 19 | input focus |
| A11Y_CLEAR_FOCUS | 20 |  |
| A11Y_COPY | 21 |  |
| A11Y_CUT | 22 |  |
| A11Y_PASTE | 23 |  |



<a name="tap-v1-SystemPanel"></a>

### SystemPanel
A panel System UI draws over every app, opened with `open_system_panel`.

| Name | Number | Description |
| ---- | ------ | ----------- |
| SYSTEM_PANEL_UNSPECIFIED | 0 |  |
| SYSTEM_PANEL_NOTIFICATIONS | 1 | the notification shade |
| SYSTEM_PANEL_QUICK_SETTINGS | 2 | the quick settings panel |


 

 

 



<a name="failure-proto"></a>

## failure.proto



<a name="tap-v1-Failure"></a>

### Failure



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| reason | [FailureReason](#tap-v1-FailureReason) |  |  |
| serial | [string](#string) |  | The device the failure is about, when there is one. |
| waited_ms | [int64](#int64) |  | DEVICE_BUSY: how long the lock was waited for. HOST_WAIT_TIMEOUT: how long the wait ran. |
| error_code | [ErrorCode](#tap-v1-ErrorCode) |  | DRIVER_COMMAND / DRIVER_TRANSPORT: the driver or transport error code and its detail. |
| detail | [string](#string) |  |  |





 


<a name="tap-v1-FailureReason"></a>

### FailureReason


| Name | Number | Description |
| ---- | ------ | ----------- |
| FAILURE_REASON_UNSPECIFIED | 0 |  |
| FAILURE_REASON_INTERNAL | 1 | A bug in the daemon or host core (INTERNAL). Report it with the daemon log. |
| FAILURE_REASON_INVALID_ARGUMENT | 2 | Caller input the daemon rejects before doing anything (INVALID_ARGUMENT). |
| FAILURE_REASON_UNAUTHENTICATED | 3 | Missing or wrong daemon token (UNAUTHENTICATED). |
| FAILURE_REASON_UNKNOWN_CLIENT_CONNECTION | 4 | The client_connection_id is not (or no longer) known (NOT_FOUND). |
| FAILURE_REASON_UNKNOWN_ATTACHED_DEVICE | 5 | The attached_device_id is not (or no longer) attached (NOT_FOUND). |
| FAILURE_REASON_NOT_OWNER | 6 | The device is attached by another client connection (PERMISSION_DENIED). |
| FAILURE_REASON_DEVICE_BUSY | 7 | Another session holds the device&#39;s lock: FAILED_PRECONDITION without a wait, DEADLINE_EXCEEDED after `waited_ms`. |
| FAILURE_REASON_DEVICE_QUARANTINED | 8 | The device&#39;s journal keeps it out of service until an explicit reset (FAILED_PRECONDITION). |
| FAILURE_REASON_HOST_WAIT_TIMEOUT | 9 | A host-side wait (app process, window, idle) ran out of time (DEADLINE_EXCEEDED). |
| FAILURE_REASON_ADB_TIMEOUT | 10 | An ADB command did not finish within its timeout (DEADLINE_EXCEEDED). |
| FAILURE_REASON_ADB_FAILED | 11 | An ADB command failed, or is gated by an earlier unreaped one (UNAVAILABLE). |
| FAILURE_REASON_ADB_REAP_UNCERTAIN | 12 | An ADB command left an uncertain residual; the device may have changed (FAILED_PRECONDITION). |
| FAILURE_REASON_APP_LIFECYCLE | 13 | An app lifecycle postcondition did not hold (FAILED_PRECONDITION). |
| FAILURE_REASON_DRIVER_BUILD_MISMATCH | 14 | The installed driver is not the build this daemon expects (FAILED_PRECONDITION). |
| FAILURE_REASON_DRIVER_START_FAILED | 15 | The driver could not be started or authenticated (UNAVAILABLE). |
| FAILURE_REASON_DRIVER_TRANSPORT | 16 | The driver connection was lost around a host-issued command (UNAVAILABLE). |
| FAILURE_REASON_DRIVER_COMMAND | 17 | A host-issued driver command (for example attach&#39;s device info) failed with `error_code` (FAILED_PRECONDITION). |
| FAILURE_REASON_SESSION_UNUSABLE | 18 | The session can no longer run operations: detach and attach again (ABORTED). |
| FAILURE_REASON_DAEMON_PRECONDITION | 19 | The daemon cannot serve the request in its current state (FAILED_PRECONDITION). |
| FAILURE_REASON_UNKNOWN_REF | 20 | The ref is not in the attached device&#39;s latest screen snapshot (NOT_FOUND). |
| FAILURE_REASON_REF_NOT_ADDRESSABLE | 21 | The ref&#39;s node had no selector that matched it alone (FAILED_PRECONDITION). |
| FAILURE_REASON_UNSUPPORTED_API | 22 | The device&#39;s API level is below what the call needs; `detail` names it (FAILED_PRECONDITION). |
| FAILURE_REASON_DEVICE_SETTING | 23 | The device did not take a setting: it read back another value (FAILED_PRECONDITION). |
| FAILURE_REASON_DEVICE_FILE | 24 | A device file Tap cannot write or read as asked: it exists and is not this session&#39;s, its directory is missing, it is not a regular file, or it did not read back (FAILED_PRECONDITION). |


 

 

 



<a name="event_log-proto"></a>

## event_log.proto



<a name="tap-v1-AppCall"></a>

### AppCall
An AppService call. `operation` is the RPC in snake_case: install, uninstall, force_stop,
clear_data, grant_permission, revoke_permission, launch, cold_launch, foreground, open_link,
set_locales.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| operation | [string](#string) |  |  |
| package_name | [string](#string) |  |  |
| activity | [string](#string) | optional | launch / cold_launch. |
| permission | [string](#string) | optional | grant_permission / revoke_permission. |
| timeout_ms | [int64](#int64) | optional | The explicit timeout the call carried. |
| uri | [string](#string) | optional | open_link. |
| any_app | [bool](#bool) | optional |  |
| extras | [IntentExtra](#tap-v1-IntentExtra) | repeated | launch / cold_launch with extras. |
| locales | [string](#string) | repeated | set_locales. |






<a name="tap-v1-DeviceCall"></a>

### DeviceCall
A DeviceService condition call. `operation` is the RPC in snake_case: set_animations,
set_dark_mode, set_font_scale, set_density, set_network, set_system_locales,
set_location, push_file, pull_file, add_media, set_stay_awake, set_accessibility_display.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| operation | [string](#string) |  |  |
| enabled | [bool](#bool) | optional | set_animations / set_dark_mode. |
| font_scale | [float](#float) | optional | set_font_scale. |
| density_dpi | [int32](#int32) | optional | set_density; absent there = back to the physical density. |
| airplane_mode | [bool](#bool) | optional | set_network: the switches the call set. |
| wifi | [bool](#bool) | optional |  |
| mobile_data | [bool](#bool) | optional |  |
| locales | [string](#string) | repeated | set_system_locales. |
| latitude | [double](#double) | optional | set_location (with accuracy_m / altitude_m below). |
| longitude | [double](#double) | optional |  |
| device_path | [string](#string) | optional | push_file / pull_file / add_media: the device file and its size. |
| size_bytes | [int64](#int64) | optional |  |
| high_contrast_text | [bool](#bool) | optional | set_accessibility_display: the settings the call set (set_stay_awake uses `enabled`). |
| color_inversion | [bool](#bool) | optional |  |
| bold_text | [bool](#bool) | optional |  |
| accuracy_m | [float](#float) | optional | set_location: the accuracy and altitude the call gave. |
| altitude_m | [double](#double) | optional |  |






<a name="tap-v1-LoggedEvent"></a>

### LoggedEvent



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| seq | [int64](#int64) |  | 1, 2, 3, … per connection; never reused. |
| at_epoch_ms | [int64](#int64) |  | When the call started. |
| duration_ms | [int64](#int64) |  |  |
| serial | [string](#string) |  |  |
| command | [Command](#tap-v1-Command) |  |  |
| app | [AppCall](#tap-v1-AppCall) |  |  |
| device | [DeviceCall](#tap-v1-DeviceCall) |  |  |
| error | [Error](#tap-v1-Error) | optional | The command ran and the driver returned an error (`CommandResult.error`). |
| failure | [Failure](#tap-v1-Failure) | optional | The call failed as an RPC (the `tap-failure-bin` trailer), e.g. an app lifecycle failure. |
| started_monotonic_ns | [int64](#int64) | optional | Host boundaries around the validated RPC block, including queued/transport work. Not device input/capture times. Compare with video receipt only when clock_id matches. Missing on events from older daemons; never derive these from epoch timestamps. |
| finished_monotonic_ns | [int64](#int64) | optional |  |
| clock_id | [string](#string) |  |  |





 

 

 

 



<a name="client_connection-proto"></a>

## client_connection.proto



<a name="tap-v1-AttachedDeviceEntry"></a>

### AttachedDeviceEntry



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| attached_device_id | [string](#string) |  |  |
| serial | [string](#string) |  |  |
| generation | [int64](#int64) |  |  |






<a name="tap-v1-Closing"></a>

### Closing
The daemon is disconnecting this client (Disconnect, reaping or shutdown); the stream ends next.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| reason | [string](#string) |  |  |






<a name="tap-v1-ConnectRequest"></a>

### ConnectRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| name | [string](#string) |  |  |
| hold | [Hold](#tap-v1-Hold) | optional | Present: a held connection. It needs no Observe stream (opening one is FAILED_PRECONDITION) and ends on Disconnect, daemon shutdown, or `idle_timeout_ms` after the last call that named it. Its `name` must be non-blank and unique among held connections (FAILED_PRECONDITION). |






<a name="tap-v1-ConnectResponse"></a>

### ConnectResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |






<a name="tap-v1-ConnectionEntry"></a>

### ConnectionEntry



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| name | [string](#string) |  |  |
| hold | [Hold](#tap-v1-Hold) | optional | Set for a held connection. |
| idle_ms | [int64](#int64) |  | Since the last call that named the connection. |
| attached_devices | [AttachedDeviceEntry](#tap-v1-AttachedDeviceEntry) | repeated |  |






<a name="tap-v1-Defaults"></a>

### Defaults



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| action_timeout_ms | [int64](#int64) |  | Attach without `default_timeout_ms` (the timeout of every command without its own), and force-stop, clear-data and process queries without `timeout_ms`. |
| wait_timeout_ms | [int64](#int64) |  | `AwaitIdle` without `timeout_ms`. |
| lifecycle_timeout_ms | [int64](#int64) |  | Install, launch and cold launch without `timeout_ms`. |
| idle_stable_ms | [int64](#int64) |  | `AwaitIdle` without `stable_for_ms`. |
| acquire_timeout_ms | [int64](#int64) |  | How long clients wait for a device another session holds (Attach `lease_timeout_ms`). |






<a name="tap-v1-DisconnectRequest"></a>

### DisconnectRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |






<a name="tap-v1-DisconnectResponse"></a>

### DisconnectResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| attached_devices_detached | [int32](#int32) |  |  |






<a name="tap-v1-EventsRequest"></a>

### EventsRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| after_seq | [int64](#int64) |  | Only events with a larger `seq`; 0 for all that are kept. |






<a name="tap-v1-EventsResponse"></a>

### EventsResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| events | [LoggedEvent](#tap-v1-LoggedEvent) | repeated |  |
| dropped | [int64](#int64) |  | Events evicted from the log since the connection began (the log keeps the last 2000). |






<a name="tap-v1-Heartbeat"></a>

### Heartbeat
Idle traffic so proxies keep the stream open; not a death detector.






<a name="tap-v1-Hold"></a>

### Hold



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| idle_timeout_ms | [int64](#int64) |  | 1000..86400000. |






<a name="tap-v1-InfoRequest"></a>

### InfoRequest







<a name="tap-v1-InfoResponse"></a>

### InfoResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| daemon_version | [string](#string) |  |  |
| host_build_id | [string](#string) |  |  |
| protocol_version | [string](#string) |  |  |
| adb_executable | [string](#string) |  |  |
| state_dir | [string](#string) |  |  |
| driver_available | [bool](#bool) |  | Whether attach installs a driver this daemon carries (bundled, or `tap serve --driver-apk`). |
| pid | [int64](#int64) |  |  |
| defaults | [Defaults](#tap-v1-Defaults) |  | The defaults the daemon applies to an omitted timeout; clients use the same numbers. |






<a name="tap-v1-ListConnectionsRequest"></a>

### ListConnectionsRequest







<a name="tap-v1-ListConnectionsResponse"></a>

### ListConnectionsResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| connections | [ConnectionEntry](#tap-v1-ConnectionEntry) | repeated |  |






<a name="tap-v1-ObserveRequest"></a>

### ObserveRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |






<a name="tap-v1-ObserveResponse"></a>

### ObserveResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| at_epoch_ms | [int64](#int64) |  |  |
| observing | [Observing](#tap-v1-Observing) |  |  |
| heartbeat | [Heartbeat](#tap-v1-Heartbeat) |  |  |
| closing | [Closing](#tap-v1-Closing) |  |  |






<a name="tap-v1-Observing"></a>

### Observing
The stream is registered; everything the connection attaches from now on is owned by it.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |





 

 

 


<a name="tap-v1-ClientConnectionService"></a>

### ClientConnectionService


| Method Name | Request Type | Response Type | Description |
| ----------- | ------------ | ------------- | ------------|
| Connect | [ConnectRequest](#tap-v1-ConnectRequest) | [ConnectResponse](#tap-v1-ConnectResponse) |  |
| Observe | [ObserveRequest](#tap-v1-ObserveRequest) | [ObserveResponse](#tap-v1-ObserveResponse) stream | Long-lived stream the client keeps open for the life of the connection; it must be opened shortly after Connect. Its end is the liveness signal: the stream ending (either side) disconnects the client. The first event is `observing`; a daemon-initiated disconnect sends `closing` and then completes the stream normally. |
| Disconnect | [DisconnectRequest](#tap-v1-DisconnectRequest) | [DisconnectResponse](#tap-v1-DisconnectResponse) |  |
| Info | [InfoRequest](#tap-v1-InfoRequest) | [InfoResponse](#tap-v1-InfoResponse) |  |
| ListConnections | [ListConnectionsRequest](#tap-v1-ListConnectionsRequest) | [ListConnectionsResponse](#tap-v1-ListConnectionsResponse) | Every live connection with its attached devices; how a later process finds a held connection by name. |
| Events | [EventsRequest](#tap-v1-EventsRequest) | [EventsResponse](#tap-v1-EventsResponse) | The connection&#39;s event log (`event_log.proto`) after `after_seq`. Kept for every connection, the last 2000 events; renews a held connection like any call naming it. |

 



<a name="device-proto"></a>

## device.proto



<a name="tap-v1-AddMediaHeader"></a>

### AddMediaHeader



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| file_name | [string](#string) |  | 1-127 letters, digits, &#39;.&#39;, &#39;_&#39;, &#39;-&#39; or spaces, ending in a photo (jpg, jpeg, png, gif, webp, heic, heif, bmp) or video (mp4, 3gp, webm, mkv, mov) extension. |
| size_bytes | [int64](#int64) |  |  |






<a name="tap-v1-AddMediaRequest"></a>

### AddMediaRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| header | [AddMediaHeader](#tap-v1-AddMediaHeader) |  |  |
| chunk | [bytes](#bytes) |  |  |






<a name="tap-v1-AddMediaResponse"></a>

### AddMediaResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| device_path | [string](#string) |  | where the media landed |






<a name="tap-v1-AttachRequest"></a>

### AttachRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| serial | [string](#string) |  |  |
| skip_driver_install | [bool](#bool) | optional | Skip installing the daemon&#39;s driver (bundled or `tap serve --driver-apk`): the device already has the right one. |
| default_timeout_ms | [int64](#int64) | optional |  |
| lease_timeout_ms | [int64](#int64) | optional | How long to wait for another session&#39;s lock on the serial; absent = fail at once. |






<a name="tap-v1-AttachResponse"></a>

### AttachResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| attached_device_id | [string](#string) |  |  |
| serial | [string](#string) |  |  |
| generation | [int64](#int64) |  |  |
| device_info | [DeviceInfo](#tap-v1-DeviceInfo) |  |  |






<a name="tap-v1-DetachRequest"></a>

### DetachRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |






<a name="tap-v1-DetachResponse"></a>

### DetachResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| clean | [bool](#bool) |  | False when cleanup timed out or the session was quarantined; `detail` says why. |
| detail | [string](#string) | optional |  |






<a name="tap-v1-DeviceEntry"></a>

### DeviceEntry
One listed device. Anything richer than the serial comes from DeviceInfo after attachment.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| serial | [string](#string) |  |  |
| state | [DeviceState](#tap-v1-DeviceState) |  |  |
| client_connection_id | [string](#string) | optional | The holding connection when this daemon holds it (LEASED); absent for another process. |
| quarantine_reason | [string](#string) | optional |  |






<a name="tap-v1-DriverLogRequest"></a>

### DriverLogRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |






<a name="tap-v1-DriverLogResponse"></a>

### DriverLogResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| lines | [string](#string) | repeated |  |






<a name="tap-v1-ExecuteRequest"></a>

### ExecuteRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| command | [Command](#tap-v1-Command) |  |  |






<a name="tap-v1-ExecuteResponse"></a>

### ExecuteResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| result | [CommandResult](#tap-v1-CommandResult) |  |  |






<a name="tap-v1-GetForegroundActivityRequest"></a>

### GetForegroundActivityRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |






<a name="tap-v1-GetForegroundActivityResponse"></a>

### GetForegroundActivityResponse
Both set, or both absent when no activity is resumed.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| package_name | [string](#string) | optional |  |
| activity | [string](#string) | optional | the fully qualified class name |






<a name="tap-v1-ListDevicesRequest"></a>

### ListDevicesRequest







<a name="tap-v1-ListDevicesResponse"></a>

### ListDevicesResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| devices | [DeviceEntry](#tap-v1-DeviceEntry) | repeated |  |






<a name="tap-v1-PullFileRequest"></a>

### PullFileRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| device_path | [string](#string) |  |  |






<a name="tap-v1-PullFileResponse"></a>

### PullFileResponse
The first message carries `size_bytes`; every message may carry a chunk.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| size_bytes | [int64](#int64) |  |  |
| chunk | [bytes](#bytes) |  |  |






<a name="tap-v1-PushFileHeader"></a>

### PushFileHeader



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| device_path | [string](#string) |  |  |
| size_bytes | [int64](#int64) |  | exact size; the upload is rejected on mismatch |






<a name="tap-v1-PushFileRequest"></a>

### PushFileRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| header | [PushFileHeader](#tap-v1-PushFileHeader) |  | first message only |
| chunk | [bytes](#bytes) |  | every later message |






<a name="tap-v1-PushFileResponse"></a>

### PushFileResponse







<a name="tap-v1-ResolveRefRequest"></a>

### ResolveRefRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| ref | [string](#string) |  | With or without the leading `@`. |






<a name="tap-v1-ResolveRefResponse"></a>

### ResolveRefResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| by_index | [bool](#bool) |  |  |
| snapshot_id | [int64](#int64) |  |  |






<a name="tap-v1-ScreenNode"></a>

### ScreenNode
One visible node, in dump (pre-order) order.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| ref | [string](#string) |  | `e&lt;N&gt;`. Stable across snapshots while the node is unchanged; never reused for another node. |
| depth | [int32](#int32) |  |  |
| window_package | [string](#string) |  | The package of the window root the node is under. |
| class_name | [string](#string) | optional |  |
| resource_name | [string](#string) | optional |  |
| text | [string](#string) | optional |  |
| content_description | [string](#string) | optional |  |
| hint | [string](#string) | optional |  |
| bounds | [Bounds](#tap-v1-Bounds) |  |  |
| flags | [NodeFlag](#tap-v1-NodeFlag) | repeated | The boolean properties that are true. |
| password | [bool](#bool) |  |  |
| interactive | [bool](#bool) |  | Clickable, long-clickable, checkable, scrollable or editable. |
| selector | [Selector](#tap-v1-Selector) | optional | A selector that matched only this node in the dump; absent when none was found. |
| by_index | [bool](#bool) |  | The selector ends in an `At` pick: correct for this dump, fragile if the screen reorders. |
| change | [NodeChange](#tap-v1-NodeChange) |  |  |
| candidates | [SelectorCandidate](#tap-v1-SelectorCandidate) | repeated | Only with ScreenSnapshotRequest.selector_candidates: every selector that matched only this node, best first (the first is `selector`). A candidate that merely adds predicates to an earlier one is left out, and a BY_INDEX pick is offered only when nothing else is unique. |
| showing_hint | [bool](#bool) |  | The field shows its hint, not a value (`AccessibilityNodeInfo.isShowingHintText`): `text` then holds the hint. False on a dump that does not report it. |
| content_invalid | [bool](#bool) |  | The app marked the content invalid (`isContentInvalid`), e.g. a field that failed validation. |
| error | [string](#string) | optional | The error the app set on the node (`getError`, e.g. `TextView.setError`). |






<a name="tap-v1-ScreenSnapshotRequest"></a>

### ScreenSnapshotRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| timeout_ms | [int64](#int64) | optional | For the hierarchy dump; absent = the attached device&#39;s default command timeout. |
| selector_candidates | [bool](#bool) |  | Also fill ScreenNode.candidates (an inspector offering the user a choice of selectors). |






<a name="tap-v1-ScreenSnapshotResponse"></a>

### ScreenSnapshotResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| snapshot_id | [int64](#int64) |  | Increases per attached device. |
| nodes | [ScreenNode](#tap-v1-ScreenNode) | repeated |  |
| removed | [ScreenNode](#tap-v1-ScreenNode) | repeated | Nodes of the previous snapshot that are gone; their refs no longer resolve. |
| rotation | [int32](#int32) |  |  |






<a name="tap-v1-ScreenshotRequest"></a>

### ScreenshotRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| timeout_ms | [int64](#int64) | optional |  |






<a name="tap-v1-ScreenshotResponse"></a>

### ScreenshotResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| png | [bytes](#bytes) |  |  |
| sha256 | [string](#string) |  |  |
| width | [int32](#int32) | optional |  |
| height | [int32](#int32) | optional |  |






<a name="tap-v1-SelectorCandidate"></a>

### SelectorCandidate
A selector that matched only its node in the dump.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| selector | [Selector](#tap-v1-Selector) |  |  |
| kind | [SelectorKind](#tap-v1-SelectorKind) |  |  |






<a name="tap-v1-SetAccessibilityDisplayRequest"></a>

### SetAccessibilityDisplayRequest
At least one setting must be set; an absent one is left as it is.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| high_contrast_text | [bool](#bool) | optional |  |
| color_inversion | [bool](#bool) | optional |  |
| bold_text | [bool](#bool) | optional |  |






<a name="tap-v1-SetAccessibilityDisplayResponse"></a>

### SetAccessibilityDisplayResponse







<a name="tap-v1-SetAnimationsRequest"></a>

### SetAnimationsRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| enabled | [bool](#bool) |  |  |






<a name="tap-v1-SetAnimationsResponse"></a>

### SetAnimationsResponse







<a name="tap-v1-SetDarkModeRequest"></a>

### SetDarkModeRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| enabled | [bool](#bool) |  |  |






<a name="tap-v1-SetDarkModeResponse"></a>

### SetDarkModeResponse







<a name="tap-v1-SetDensityRequest"></a>

### SetDensityRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| dpi | [int32](#int32) | optional | Absent: remove the override (the display&#39;s physical density). |






<a name="tap-v1-SetDensityResponse"></a>

### SetDensityResponse







<a name="tap-v1-SetFontScaleRequest"></a>

### SetFontScaleRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| scale | [float](#float) |  |  |






<a name="tap-v1-SetFontScaleResponse"></a>

### SetFontScaleResponse







<a name="tap-v1-SetLocationRequest"></a>

### SetLocationRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| latitude | [double](#double) |  |  |
| longitude | [double](#double) |  |  |
| accuracy_m | [float](#float) | optional |  |
| altitude_m | [double](#double) | optional |  |






<a name="tap-v1-SetLocationResponse"></a>

### SetLocationResponse







<a name="tap-v1-SetNetworkRequest"></a>

### SetNetworkRequest
At least one switch must be set; an absent one is left as it is.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| airplane_mode | [bool](#bool) | optional |  |
| wifi | [bool](#bool) | optional |  |
| mobile_data | [bool](#bool) | optional |  |






<a name="tap-v1-SetNetworkResponse"></a>

### SetNetworkResponse







<a name="tap-v1-SetStayAwakeRequest"></a>

### SetStayAwakeRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| enabled | [bool](#bool) |  |  |






<a name="tap-v1-SetStayAwakeResponse"></a>

### SetStayAwakeResponse







<a name="tap-v1-SetSystemLocalesRequest"></a>

### SetSystemLocalesRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| locales | [string](#string) | repeated |  |






<a name="tap-v1-SetSystemLocalesResponse"></a>

### SetSystemLocalesResponse







<a name="tap-v1-StartRecordingRequest"></a>

### StartRecordingRequest
A bounded artifact: video is H.264 MP4, audio is Opus, combined is Matroska (H.264&#43;Opus).
Clients select tracks at Start; Stop returns their one muxed file (never two scrcpy children).


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |
| video | [bool](#bool) |  |  |
| audio_source | [string](#string) |  | Empty means no audio. &#34;output&#34; (Android 11&#43;; mutes the device speakers), &#34;playback&#34; (Android 13&#43;; keeps local playback, apps can opt out) or &#34;mic&#34; (the device microphone). |
| max_seconds | [int32](#int32) |  | Absent/zero = 30 s with video, 60 s audio only. Max 30 s video / 60 s audio. |






<a name="tap-v1-StartRecordingResponse"></a>

### StartRecordingResponse







<a name="tap-v1-StopRecordingRequest"></a>

### StopRecordingRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| client_connection_id | [string](#string) |  |  |
| attached_device_id | [string](#string) |  |  |






<a name="tap-v1-StopRecordingResponse"></a>

### StopRecordingResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| data | [bytes](#bytes) |  | ≤16 MiB video, ≤3 MiB audio-only |
| format | [string](#string) |  | mp4, mkv, opus |
| sha256 | [string](#string) |  |  |





 


<a name="tap-v1-DeviceState"></a>

### DeviceState
State of a listed device.

| Name | Number | Description |
| ---- | ------ | ----------- |
| DEVICE_STATE_UNSPECIFIED | 0 |  |
| DEVICE_FREE | 1 |  |
| DEVICE_LEASED | 2 |  |
| DEVICE_QUARANTINED | 3 |  |
| DEVICE_OFFLINE | 4 |  |
| DEVICE_UNAUTHORIZED | 5 |  |



<a name="tap-v1-NodeChange"></a>

### NodeChange
A node against the previous snapshot of the same attached device.

| Name | Number | Description |
| ---- | ------ | ----------- |
| NODE_CHANGE_UNSPECIFIED | 0 | there was no previous snapshot |
| NODE_ADDED | 1 |  |
| NODE_UNCHANGED | 2 |  |
| NODE_REMOVED | 3 |  |



<a name="tap-v1-SelectorKind"></a>

### SelectorKind
How a synthesised selector singles out its node.

| Name | Number | Description |
| ---- | ------ | ----------- |
| SELECTOR_KIND_UNSPECIFIED | 0 |  |
| SELECTOR_KIND_PLAIN | 1 | One predicate: resource id, text, description or hint. |
| SELECTOR_KIND_COMBINED | 2 | Two predicates of the node itself (resource and text, text and class, ...). |
| SELECTOR_KIND_ANCESTOR | 3 | The node&#39;s own predicate plus an `ancestor` relation to an addressable ancestor. |
| SELECTOR_KIND_BY_INDEX | 4 | All of the node&#39;s predicates plus an `At` pick: correct for this dump, fragile if the screen reorders. |


 

 


<a name="tap-v1-DeviceService"></a>

### DeviceService


| Method Name | Request Type | Response Type | Description |
| ----------- | ------------ | ------------- | ------------|
| ListDevices | [ListDevicesRequest](#tap-v1-ListDevicesRequest) | [ListDevicesResponse](#tap-v1-ListDevicesResponse) |  |
| Attach | [AttachRequest](#tap-v1-AttachRequest) | [AttachResponse](#tap-v1-AttachResponse) |  |
| Detach | [DetachRequest](#tap-v1-DetachRequest) | [DetachResponse](#tap-v1-DetachResponse) |  |
| Execute | [ExecuteRequest](#tap-v1-ExecuteRequest) | [ExecuteResponse](#tap-v1-ExecuteResponse) |  |
| Screenshot | [ScreenshotRequest](#tap-v1-ScreenshotRequest) | [ScreenshotResponse](#tap-v1-ScreenshotResponse) |  |
| DriverLog | [DriverLogRequest](#tap-v1-DriverLogRequest) | [DriverLogResponse](#tap-v1-DriverLogResponse) |  |
| StartRecording | [StartRecordingRequest](#tap-v1-StartRecordingRequest) | [StartRecordingResponse](#tap-v1-StartRecordingResponse) | One optional host-managed scrcpy capture per attachment (video, audio or both); the driver never encodes media. Requires scrcpy on the daemon host. |
| StopRecording | [StopRecordingRequest](#tap-v1-StopRecordingRequest) | [StopRecordingResponse](#tap-v1-StopRecordingResponse) |  |
| ScreenSnapshot | [ScreenSnapshotRequest](#tap-v1-ScreenSnapshotRequest) | [ScreenSnapshotResponse](#tap-v1-ScreenSnapshotResponse) | A compact, ref-addressed outline of the screen, parsed from the diagnostic hierarchy dump (`.docs/agent-surface.md`). Refs name selectors the daemon synthesised, never node handles. |
| ResolveRef | [ResolveRefRequest](#tap-v1-ResolveRefRequest) | [ResolveRefResponse](#tap-v1-ResolveRefResponse) | The selector a ref of the latest snapshot names. Unknown ref: NOT_FOUND (UNKNOWN_REF); a node with no selector: FAILED_PRECONDITION (REF_NOT_ADDRESSABLE). |
| SetAnimations | [SetAnimationsRequest](#tap-v1-SetAnimationsRequest) | [SetAnimationsResponse](#tap-v1-SetAnimationsResponse) | Device-wide conditions. Each changed value is captured before the session&#39;s first change of it, journaled, and restored when the device is detached (or by the next attach when the daemon died first); a restore that cannot be proven quarantines the device. Every change is read back: a value the device did not take is FAILED_PRECONDITION (DEVICE_SETTING). The three animation scales (window, transition, animator duration): all 0 or all 1. |
| SetDarkMode | [SetDarkModeRequest](#tap-v1-SetDarkModeRequest) | [SetDarkModeResponse](#tap-v1-SetDarkModeResponse) | `cmd uimode night yes|no`. API 29&#43; (FAILED_PRECONDITION, UNSUPPORTED_API below). |
| SetFontScale | [SetFontScaleRequest](#tap-v1-SetFontScaleRequest) | [SetFontScaleResponse](#tap-v1-SetFontScaleResponse) | The system font scale (`font_scale`), 0.5 to 2.0. |
| SetDensity | [SetDensityRequest](#tap-v1-SetDensityRequest) | [SetDensityResponse](#tap-v1-SetDensityResponse) | `wm density`: an override in dpi (100 to 1000), or absent for the display&#39;s physical density. |
| SetNetwork | [SetNetworkRequest](#tap-v1-SetNetworkRequest) | [SetNetworkResponse](#tap-v1-SetNetworkResponse) | Airplane mode (`cmd connectivity airplane-mode`), Wi-Fi (`svc wifi`) and mobile data (`svc data`): the real switches, nothing mocked. API 29&#43;. Airplane mode is written first; all three are captured on the first change and restored airplane mode first. A device reached over ADB on the network refuses Wi-Fi off / airplane mode on (FAILED_PRECONDITION). |
| SetSystemLocales | [SetSystemLocalesRequest](#tap-v1-SetSystemLocalesRequest) | [SetSystemLocalesResponse](#tap-v1-SetSystemLocalesResponse) | The device-wide locale list (Settings › Languages), 1 to 16 BCP-47 tags in preference order (INVALID_ARGUMENT otherwise). Android has no shell command for it: the driver app applies it as Settings&#39; language picker does, and it is read back (`system_locales`). |
| SetLocation | [SetLocationRequest](#tap-v1-SetLocationRequest) | [SetLocationResponse](#tap-v1-SetLocationResponse) | Mock location: the device reports this fix from its location providers until detach. `latitude` -90..90, `longitude` -180..180, `accuracy_m` &gt; 0 (default 5), `altitude_m` finite (INVALID_ARGUMENT otherwise). The driver app becomes the mock-location app (its `android:mock_location` app-op) and location is turned on when it is off; both are captured and restored on detach, which ends the mock. The driver serves the fix (`set_location`). |
| SetStayAwake | [SetStayAwakeRequest](#tap-v1-SetStayAwakeRequest) | [SetStayAwakeResponse](#tap-v1-SetStayAwakeResponse) | Keeps the screen on while the device is plugged in (USB, AC or wireless): Settings.Global `stay_on_while_plugged_in` 7, or 0. Captured and restored on detach. |
| SetAccessibilityDisplay | [SetAccessibilityDisplayRequest](#tap-v1-SetAccessibilityDisplayRequest) | [SetAccessibilityDisplayResponse](#tap-v1-SetAccessibilityDisplayResponse) | The accessibility display settings: high-contrast text, color inversion and bold text (API 31&#43;, else FAILED_PRECONDITION / UNSUPPORTED_API before anything changes), as Settings › Accessibility writes them. At least one must be set. Captured and restored on detach. |
| GetForegroundActivity | [GetForegroundActivityRequest](#tap-v1-GetForegroundActivityRequest) | [GetForegroundActivityResponse](#tap-v1-GetForegroundActivityResponse) | The activity on top (resumed), from `dumpsys activity activities`; empty when none is resumed (a keyguard, or between activities). Changes nothing. |
| PushFile | [PushFileRequest](#tap-v1-PushFileRequest) stream | [PushFileResponse](#tap-v1-PushFileResponse) | Files. The bytes travel in the call (never a path on the server&#39;s machine), at most 512 MiB. A file Tap cannot write or read as asked is FAILED_PRECONDITION / DEVICE_FILE.

Copies a file to `device_path` (absolute, normalised; its directory must exist): a PushFileHeader first, then the bytes. A file already there is refused unless this attached device pushed it; the size is read back. Pushed files are deleted on detach. |
| PullFile | [PullFileRequest](#tap-v1-PullFileRequest) | [PullFileResponse](#tap-v1-PullFileResponse) stream | Streams the regular file at `device_path` back in chunks. |
| AddMedia | [AddMediaRequest](#tap-v1-AddMediaRequest) stream | [AddMediaResponse](#tap-v1-AddMediaResponse) | Adds a photo or video to the gallery: an AddMediaHeader (`file_name` with a photo or video extension), then the bytes. Written to `/sdcard/Pictures/Tap/` or `/sdcard/Movies/Tap/` and indexed by the media scanner (read back); a name already there is refused unless this attached device added it. Deleted, and dropped from the index, on detach. |

 



<a name="watch-proto"></a>

## watch.proto



<a name="tap-v1-Activity"></a>

### Activity
One thing that happened, numbered 1, 2, 3, … for the daemon&#39;s lifetime.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| seq | [int64](#int64) |  |  |
| at_epoch_ms | [int64](#int64) |  |  |
| client_connection_id | [string](#string) |  |  |
| connection_opened | [ConnectionOpened](#tap-v1-ConnectionOpened) |  |  |
| connection_closed | [ConnectionClosed](#tap-v1-ConnectionClosed) |  |  |
| device_attached | [DeviceAttached](#tap-v1-DeviceAttached) |  |  |
| device_detached | [DeviceDetached](#tap-v1-DeviceDetached) |  |  |
| event | [LoggedEvent](#tap-v1-LoggedEvent) |  | A call the connection made, exactly as its own event log (`Events`) records it. |






<a name="tap-v1-ConnectionClosed"></a>

### ConnectionClosed



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| reason | [string](#string) |  |  |






<a name="tap-v1-ConnectionOpened"></a>

### ConnectionOpened



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| name | [string](#string) |  |  |
| held | [bool](#bool) |  | Set for a held connection. |






<a name="tap-v1-DeviceAttached"></a>

### DeviceAttached



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| attached_device_id | [string](#string) |  |  |
| serial | [string](#string) |  |  |
| generation | [int64](#int64) |  |  |






<a name="tap-v1-DeviceDetached"></a>

### DeviceDetached



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| attached_device_id | [string](#string) |  |  |
| serial | [string](#string) |  |  |
| reason | [string](#string) |  | &#34;detached&#34;, or why its connection ended. |






<a name="tap-v1-VideoFrame"></a>

### VideoFrame



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| seq | [uint64](#uint64) |  | 1, 2, 3, … per stream_id. |
| pts_us | [int64](#int64) |  |  |
| key_frame | [bool](#bool) |  |  |
| data | [bytes](#bytes) |  |  |
| received_monotonic_ns | [int64](#int64) |  | Host receipt of the full packet on the clock `clock_id` names — the clock of `LoggedEvent.started_monotonic_ns`. Not device capture or input execution time. |
| received_epoch_ms | [int64](#int64) |  |  |






<a name="tap-v1-VideoHeader"></a>

### VideoHeader



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| stream_id | [string](#string) |  |  |
| clock_id | [string](#string) |  |  |
| width | [uint32](#uint32) |  |  |
| height | [uint32](#uint32) |  |  |
| configuration | [bytes](#bytes) |  | H.264 Annex B SPS/PPS. A new header resets the decoder. |






<a name="tap-v1-WatchRequest"></a>

### WatchRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| after_seq | [int64](#int64) |  | Only activity with a larger seq; 0 for the whole retained backlog. Must be &gt;= 0. |






<a name="tap-v1-WatchResponse"></a>

### WatchResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| connections | [ConnectionEntry](#tap-v1-ConnectionEntry) | repeated | First response only: every live connection with its attached devices when the stream began. |
| activities | [Activity](#tap-v1-Activity) | repeated | In seq order. The first response holds the backlog (possibly empty); later ones are live. |
| dropped | [int64](#int64) |  | Activities evicted from the daemon&#39;s log since it started (it keeps the last 10000). |






<a name="tap-v1-WatchVideoRequest"></a>

### WatchVideoRequest



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| serial | [string](#string) |  |  |






<a name="tap-v1-WatchVideoResponse"></a>

### WatchVideoResponse



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| header | [VideoHeader](#tap-v1-VideoHeader) |  |  |
| frame | [VideoFrame](#tap-v1-VideoFrame) |  |  |





 

 

 


<a name="tap-v1-WatchService"></a>

### WatchService


| Method Name | Request Type | Response Type | Description |
| ----------- | ------------ | ------------- | ------------|
| Watch | [WatchRequest](#tap-v1-WatchRequest) | [WatchResponse](#tap-v1-WatchResponse) stream | The daemon-wide activity log after `after_seq`: the retained backlog, then live activity as it happens, until the client cancels or the daemon stops. The first response also carries the live connections, so names survive eviction of their `connection_opened`. |
| WatchVideo | [WatchVideoRequest](#tap-v1-WatchVideoRequest) | [WatchVideoResponse](#tap-v1-WatchVideoResponse) stream | One device&#39;s screen as H.264, from a scrcpy server the daemon runs while anyone watches that serial; readers of one serial share it. Needs `tap start --scrcpy-server`. No input, no screen wake, no attachment. |

 



## Scalar Value Types

| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- |
| <a name="double" /> double |  | double | double | float | float64 | double | float | Float |
| <a name="float" /> float |  | float | float | float | float32 | float | float | Float |
| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) |
| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) |
| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) |
| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum |
| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="bool" /> bool |  | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass |
| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |

