Skip to content
This repository has been archived by the owner on Nov 29, 2022. It is now read-only.

Commit

Permalink
adblib: add support for exec service
Browse files Browse the repository at this point in the history
`exec` is the same as `shell`, except `stderr` is discarded.

* Also, change `abb_exec` implementation to re-use same code as `shell` and `exec

* Also, refactor FakeAdbServer `exec` support to follow same pattern as `shell`, i.e. one sub-class per command supported.

Bug: 188067646
Test: Included
Change-Id: I3feda1ec39bfb8b0c9232e1447cb9340d518b08d
  • Loading branch information
rpaquay committed Mar 24, 2022
1 parent b54f124 commit 1d5c8e1
Show file tree
Hide file tree
Showing 17 changed files with 674 additions and 200 deletions.
80 changes: 77 additions & 3 deletions adblib/src/com/android/adblib/AdbDeviceServices.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,17 @@ interface AdbDeviceServices {

/**
* Returns a [Flow] that, when collected, executes a shell command on a device
* ("<device-transport>:shell" query) and emits the output of the command to the [Flow].
* ("<device-transport>:shell" query) and emits the `stdout` and `stderr` output from of
* the command to the [Flow].
*
* This is the equivalent of running "`/system/bin/sh -c `[command]" on the [device], meaning
* [command] can be any arbitrary shell invocation, including pipes and redirections, as
* opposed to executing a single process.
*
* __Note__: When collecting the command output, there is no way to distinguish between
* `stdout` or `stderr`, i.e. both streams are merged. There is also no way to know
* the `exit code` of the shell command. It is recommended to use [shellV2] instead for
* devices that support [AdbFeatures.SHELL_V2].
*
* The returned [Flow] elements are collected and emitted through a [ShellCollector],
* which enables advanced use cases for collecting, mapping, filtering and joining
Expand All @@ -54,6 +64,8 @@ interface AdbDeviceServices {
* device connection has been successfully established. If the command takes more time than
* the timeout, a [TimeoutException] is thrown and the underlying [AdbChannel] is closed.
* @param [bufferSize] the size of the buffer used to receive data from the shell command output
*
* @see [shellV2]
*/
fun <T> shell(
device: DeviceSelector,
Expand All @@ -64,6 +76,29 @@ interface AdbDeviceServices {
bufferSize: Int = DEFAULT_SHELL_BUFFER_SIZE,
): Flow<T>

/**
* Returns a [Flow] that, when collected, executes a shell command on a device
* ("<device-transport>:exec" query) and emits the `stdout` output from of
* the command to the [Flow].
*
* See [shell] for a more detailed description. The main difference with [shell] is this
* service only captures `stdout` and ignores `stderr`.
*
* __Note__: When collecting the command output, there is no way to access the contents
* of `stderr`. There is also no way to know the `exit code` of the shell command.
* It is recommended to use [shellV2] instead for devices that support [AdbFeatures.SHELL_V2].
*
* @see [shellV2]
*/
fun <T> exec(
device: DeviceSelector,
command: String,
shellCollector: ShellCollector<T>,
stdinChannel: AdbInputChannel? = null,
commandTimeout: Duration = INFINITE_DURATION,
bufferSize: Int = DEFAULT_SHELL_BUFFER_SIZE,
): Flow<T>

/**
* Returns a [Flow] that, when collected, executes a shell command on a device
* ("<device-transport>:shell,v2" query) and emits the output, as well as `stderr` and
Expand All @@ -83,7 +118,7 @@ interface AdbDeviceServices {
*
* __Note__: Support for the "shell v2" protocol was added in Android API 24 (Nougat).
* To verify the protocol is supported by the target device, call the
* [AdbHostServices.features] method and look for the "shell_v2" element in the
* [AdbHostServices.features] method and look for the [AdbFeatures.SHELL_V2] element in the
* resulting [List]. If protocol is not supported by the device, the returned [Flow] throws
* an [AdbFailResponseException].
*
Expand All @@ -107,7 +142,46 @@ interface AdbDeviceServices {
bufferSize: Int = DEFAULT_SHELL_BUFFER_SIZE,
): Flow<T>


/**
* Returns a [Flow] that, when collected, executes a "Android Binder Bridge" command on
* a device ("<device-transport>:abb_exec" query) and emits the `stdout` output from of
* the command to the [Flow]. This is the equivalent of running "`cmd `[command]" using
* [exec], except throughput is much higher.
*
* __Note__: To verify the "abb" protocol is supported by the target device, callers
* should invoke the [AdbHostServices.features] method and look for the
* [AdbFeatures.ABB_EXEC] element in the resulting [List]. If protocol is not supported
* by the device, the returned [Flow] throws an [AdbFailResponseException] and callers
* should fall back to using [shellV2] or [exec] with the equivalent "`cmd`" shell command.
*
* __Note__: When collecting the command output, there is no way to access the contents
* of `stderr`. There is also no way to know the `exit code` of the command.
*
* The returned [Flow] elements are collected and emitted through a [ShellCollector],
* which enables advanced use cases for collecting, mapping, filtering and joining
* the command output which is initially collected as [ByteBuffer]. A typical use
* case is to use a [ShellCollector] that decodes the output as a [Flow] of [String],
* one for each line of the output.
*
* The flow is active until an exception is thrown, cancellation is requested by
* the flow consumer, or the shell command is terminated.
*
* The flow can throw [AdbProtocolErrorException], [AdbFailResponseException],
* [IOException] or any [Exception] thrown by [shellCollector]
*
* @param [device] the [DeviceSelector] corresponding to the target device
* @param [command] the "abb" command to execute
* @param [shellCollector] The [ShellCollector] invoked to collect the shell command output
* and emit elements to the resulting [Flow]
* @param [stdinChannel] is an optional [AdbChannel] providing bytes to send to the `stdin`
* of the shell command
* @param [commandTimeout] timeout tracking the command execution, tracking starts *after* the
* device connection has been successfully established. If the command takes more time than
* the timeout, a [TimeoutException] is thrown and the underlying [AdbChannel] is closed.
* @param [bufferSize] the size of the buffer used to receive data from the shell command output
*
* @see [shellV2]
*/
fun <T> abb_exec(
device: DeviceSelector,
command: List<String>,
Expand Down
36 changes: 36 additions & 0 deletions adblib/src/com/android/adblib/AdbFeatures.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.adblib

/**
* Identifier of optional features supported by the ADB host and/or ADB daemon.
* See [AdbHostServices.features].
*/
@Suppress("SpellCheckingInspection")
object AdbFeatures {

/**
* If the result of [AdbHostServices.features] contains this value, the
* [AdbDeviceServices.abb_exec] invocation is supported by the specified device.
*/
const val ABB_EXEC = "abb_exec"

/**
* If the result of [AdbHostServices.features] contains this value, the
* [AdbDeviceServices.shellV2] invocation is supported by the specified device.
*/
const val SHELL_V2 = "shell_v2"
}
2 changes: 2 additions & 0 deletions adblib/src/com/android/adblib/AdbHostServices.kt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ interface AdbHostServices {

/**
* Returns the list of features of the [device] ("<device-prefix>:features" query).
*
* See [AdbFeatures] for a (subset of the) list of possible features.
*/
suspend fun features(device: DeviceSelector): List<String>

Expand Down
Loading

0 comments on commit 1d5c8e1

Please sign in to comment.