import { Client as MonkeyClient } from '@u4/adbkit-monkey';
import Logcat from '@u4/adbkit-logcat';
import Connection from './connection';
import Sync from './sync';
import ProcStat from './proc/stat';
import * as hostCmd from './command/host-transport';
import Forward from '../models/Forward';
import Reverse from '../models/Reverse';
import StartActivityOptions from '../models/StartActivityOptions';
import StartServiceOptions from '../models/StartServiceOptions';
import { Duplex } from 'stream';
import Stats from './sync/stats';
import Entry from './sync/entry';
import PushTransfer from './sync/pushtransfer';
import { ReadStream } from 'fs';
import PullTransfer from './sync/pulltransfer';
import { Properties } from '../models/Properties';
import { Features } from '../models/Features';
import FramebufferStreamWithMeta from '../models/FramebufferStreamWithMeta';
import WithToString from '../models/WithToString';
import JdwpTracker from './jdwptracker';
import { DeviceType } from '../models/Device';
import DeviceWithPath from '../models/DeviceWithPath';
import Client from './client';
import Scrcpy from './thirdparty/scrcpy/Scrcpy';
import type { ScrcpyOptions } from './thirdparty/scrcpy/ScrcpyModels';
import { RebootType } from './command/host-transport/reboot';
import Minicap, { MinicapOptions } from './thirdparty/minicap/Minicap';
import STFService, { STFServiceOptions } from './thirdparty/STFService/STFService';
import PromiseDuplex from 'promise-duplex';
import { DeviceClientOptions } from '../models/DeviceClientOptions';
import { ParcelReader, ServiceCallArg } from './command/host-transport/serviceCall';
import DeviceClientExtra from './DeviceClientExtra';
import Stats64 from './sync/stats64';
import Entry64 from './sync/entry64';
import DevicePackage from './DevicePackage';
export default class DeviceClient {
    #private;
    readonly client: Client;
    readonly serial: string;
    private options;
    constructor(client: Client, serial: string, options?: Partial<DeviceClientOptions>);
    sudo(): DeviceClient;
    /**
     * Gets the serial number of the device identified by the given serial number. With our API this doesn't really make much sense, but it has been implemented for completeness. _FYI: in the raw ADB protocol you can specify a device in other ways, too._
     *
     * @returns The serial number of the device.
     */
    getSerialNo(): Promise<string>;
    /**
     * Gets the device path of the device identified by the given serial number.
     * @returns The device path. This corresponds to the device path in `client.listDevicesWithPaths()`.
     *
     * @example
     * List devices withPath
     * ```ts
     * import Adb from '@u4/adbkit';
     * const client = Adb.createClient();
     * const devices = client.listDevicesWithPaths();
     * devices.then((devices) => {
     *     devices.forEach(function (d) {
     *         console.log('id: ' + d.id);
     *         console.log('type: ' + d.type);
     *         console.log('model ' + d.model);
     *         console.log('path: ' + d.path);
     *         console.log('product: ' + d.product);
     *         console.log('transportId: ' + d.transportId + '\n');
     *     });
     * });
     * ```
     */
    getDevicePath(): Promise<DeviceWithPath['path']>;
    /**
     * Gets the state of the device identified by the given serial number.
     *
     * @returns The device state. This corresponds to the device type in `client.listDevices()`.
     */
    getState(): Promise<DeviceType>;
    /**
     * Retrieves the properties of the device identified by the given serial number. This is analogous to `adb shell getprop`.
     *
     * @returns An object of device properties. Each key corresponds to a device property. Convenient for accessing things like `'ro.product.model'`.
     */
    getProperties(): Promise<Properties>;
    /**
     * Retrieves the features of the device identified by the given serial number. This is analogous to `adb shell pm list features`. Useful for checking whether hardware features such as NFC are available (you'd check for `'android.hardware.nfc'`).
     *
     * @returns An object of device features. Each key corresponds to a device feature, with the value being either `true` for a boolean feature, or the feature value as a string (e.g. `'0x20000'` for `reqGlEsVersion`).
     *
     * @example
     * Checking for NFC support
     * ```ts
     * import Adb from '@u4/adbkit';
     *
     * const client = Adb.createClient();
     *
     * const test = async () => {
     *     try {
     *         const devices = await client.listDevices();
     *         const supportedDevices: string[] = [];
     *         for (const device of devices) {
     *             const client = device.client();
     *             const features = await client.getFeatures(device.id);
     *             if (features['android.hardware.nfc'])
     *                 supportedDevices.push(device.serial);
     *         }
     *         console.log('The following devices support NFC:', supportedDevices);
     *     } catch (err) {
     *         console.error('Something went wrong:', err.stack);
     *     }
     * };
     * ```
     */
    getFeatures(): Promise<Features>;
    /**
     * Retrieves the list of packages present on the device. This is analogous to `adb shell pm list packages`. If you just want to see if something's installed, consider using `client.isInstalled()` instead.
     *
     * @param flags Flags to pass to the `pm list packages` command to filter the list
     * -d: filter to only show disabled packages
     * -e: filter to only show enabled packages
     * -s: filter to only show system packages
     * -3: filter to only show third party packages
     * @returns An object of device features. Each key corresponds to a device feature, with the value being either `true` for a boolean feature, or the feature value as a string (e.g. `'0x20000'` for `reqGlEsVersion`)
     */
    getPackages(flags?: string): Promise<string[]>;
    /**
     * Retrieves the list of running Process
     *
     * @param flags TODO
     * @returns a PsEntry array
     */
    getPs(...flags: string[]): Promise<Array<Partial<hostCmd.PsEntry>>>;
    /**
     * call ip route command
     *
     * @returns a IpRouteEntry array
     */
    ipRoute(...args: string[]): Promise<Array<hostCmd.IpRouteEntry>>;
    /**
     * call ip rule command
     *
     * @returns a IpRuleEntry array
     */
    ipRule(...args: string[]): Promise<Array<hostCmd.IpRuleEntry>>;
    /**
     * Retrieves the list of available services
     *
     * @returns a PsEntry array
     */
    getServices(): Promise<Array<hostCmd.AdbServiceInfo>>;
    /**
     * Retrieves the list of available services
     *
     * @returns a PsEntry array
     */
    checkService(serviceName: hostCmd.KnownServices | string): Promise<boolean>;
    /**
     * exec a service call command and return Parcel responce Data as a Buffer
     *
     * @returns a PsEntry array
     */
    callServiceRaw(serviceName: hostCmd.KnownServices | string, code: number | string, ...args: Array<ServiceCallArg>): Promise<ParcelReader>;
    /**
     * Attemps to retrieve the IP addresses of the device. using `ip addr show` command.
     *
     * @param [iface] The network interface. Defaults to `'wlan0'`.
     *
     * @returns The IP addresses as string[] starting with IPv4 then IPv6.
     */
    getIpAddress(iface?: string): Promise<string[]>;
    /**
     * Forwards socket connections from the ADB server host (local) to the device (remote). This is analogous to `adb forward <local> <remote>`. It's important to note that if you are connected to a remote ADB server, the forward will be created on that host.
     *
     * @param local A string representing the local endpoint on the ADB host. At time of writing, can be one of:
     * -   `tcp:<port>`
     * -   `localabstract:<unix domain socket name>`
     * -   `localreserved:<unix domain socket name>`
     * -   `localfilesystem:<unix domain socket name>`
     * -   `dev:<character device name>`
     * @param remote A string representing the remote endpoint on the device. At time of writing, can be one of:
     *   Any value accepted by the `local` argument
     *   `jdwp:<process pid>`
     * @returns true
     */
    forward(local: string, remote: string): Promise<boolean>;
    /**
     * Get a localTCP port connected to remote socket, this method will try to get the requested port, but if the port is already taken, will choose an other one.
     * Note if a foward already existe to the same destination with a different port, no new foward will be create.
     * @param preferedPort the TCP port you would like to get.
     * @param remote A string representing the remote endpoint on the device. At time of writing, can be one of:
     *   Any value accepted by the `local` argument
     *   `jdwp:<process pid>`
     * @returns the used port
     */
    tryForwardTCP(remote: string, preferedPort?: number): Promise<number>;
    /**
     * Remove the port forward at ADB server host (local). This is analogous to adb forward --remove <local>. It's important to note that if you are connected to a remote ADB server, the forward on that host will be removed.
     * @param local A string representing the local endpoint on the ADB host. At time of writing, can be one of: `tcp:<port>`, `localabstract:<unix domain socket name>`, `localreserved:<unix domain socket name>`, `localfilesystem:<unix domain socket name>`, `dev:<character device name>`
     * @returns true
     */
    removeForward(local: string): Promise<boolean>;
    /**
     * Lists forwarded connections on the device. This is analogous to `adb forward --list`.
     *
     * @returns An array of forward objects with the following properties:
     *   -   **serial** The device serial.
     *   -   **local** The local endpoint. Same format as `client.forward()`'s `local` argument.
     *   -   **remote** The remote endpoint on the device. Same format as `client.forward()`'s `remote` argument.
     */
    listForwards(): Promise<Forward[]>;
    /**
     * Reverses socket connections from the device (remote) to the ADB server host (local). This is analogous to `adb reverse <remote> <local>`. It's important to note that if you are connected to a remote ADB server, the reverse will be created on that host.
     * @param remote A string representing the remote endpoint on the device. At time of writing, can be one of:
     * -   `tcp:<port>`
     * -   `localabstract:<unix domain socket name>`
     * -   `localreserved:<unix domain socket name>`
     * -   `localfilesystem:<unix domain socket name>`
     * @param local A string representing the local endpoint on the ADB host. At time of writing, can be any value accepted by the `remote` argument.
     * @return true
     */
    reverse(remote: string, local: string): Promise<true>;
    /**
     * Lists forwarded connections on the device. This is analogous to `adb reverse --list`.
     *
     * @returns An array of Reverse objects with the following properties:
     *  -   **remote** The remote endpoint on the device. Same format as `client.reverse()`'s `remote` argument.
     *  -   **local** The local endpoint on the host. Same format as `client.reverse()`'s `local` argument.
     */
    listReverses(): Promise<Reverse[]>;
    /**
     * return a new connection to ADB.
     */
    private connection;
    /**
     * return a new connextion to the current Host devices
     */
    transport(): Promise<Connection>;
    /**
     * Runs a shell command on the device. Note that you'll be limited to the permissions of the `shell` user, which ADB uses.
     *
     * @param command The shell command to execute. When `String`, the command is run as-is. When `Array`, the elements will be rudimentarily escaped (for convenience, not security) and joined to form a command.
     *
     * @returns A readable stream (`Socket` actually) containing the progressive `stdout` of the command. Use with `adb.util.readAll` to get a readable String from it.
     * @example
     * Read the output of an instantaneous command
     * ```ts
     * import Adb from '@u4/adbkit';
     *
     * try {
     *   const client = Adb.createClient();
     *   const devices = await client.listDevices();
     *   for (const device of devices) {
     *       const stream = await device.getClient().shell('echo $RANDOM');
     *       // Use the readAll() utility to read all the content without
     *       // having to deal with the readable stream. `output` will be a Buffer
     *       // containing all the output.
     *       const output = await adb.util.readAll(stream);
     *       console.log('[%s] %s', device.id, output.toString().trim());
     *   }
     *   console.log('Done.');
     * } catch(err) {
     *   console.error('Something went wrong:', err.stack);
     * }
     * ```
     * @example
     * Progressively read the output of a long-running command and terminate it
     * ```ts
     * import Adb from '@u4/adbkit';
     *
     * const client = Adb.createClient();
     * const devices = await client.listDevices()
     * for (const device of devices) {
     *   // logcat just for illustration, prefer client.openLogcat in real use
     *   const conn = await device.getClient().shell('logcat')
     *   let line = 0
     *   conn.on('data', function(data) {
     *     // here `ps` on the device shows the running logcat process
     *     console.log(data.toString())
     *     line += 1
     *     // close the stream and the running process
     *     // on the device will be gone, gracefully
     *     if (line > 100) conn.end()
     *   });
     *   conn.on('close', function() {
     *     // here `ps` on the device shows the logcat process is gone
     *     console.log('100 lines read already, bye')
     *   })
     *  }
     * console.log('Done.')
     * ```
     */
    shell(command: string | ArrayLike<WithToString>): Promise<Duplex>;
    exec(command: string | ArrayLike<WithToString>): Promise<Duplex>;
    /**
     * execute a single shell command and get stdout responce as a buffer of a string.
     * @param command the command to execute
     */
    execOut(command: string | ArrayLike<WithToString>): Promise<Buffer>;
    execOut(command: string | ArrayLike<WithToString>, encoding: BufferEncoding): Promise<string>;
    /**
     * Puts the device into root mode which may be needed by certain shell commands. A remount is generally required after a successful root call. **Note that this will only work if your device supports this feature. Production devices almost never do.**
     *
     * @return true
     */
    reboot(type?: RebootType): Promise<boolean>;
    /**
     * Attempts to remount the `/system` partition in read-write mode. This will usually only work on emulators and developer devices.
     *
     * @returns true
     */
    remount(): Promise<boolean>;
    /**
     * Puts the device into root mode which may be needed by certain shell commands. A remount is generally required after a successful root call. **Note that this will only work if your device supports this feature. Production devices almost never do.**
     *
     * @return true
     */
    root(): Promise<boolean>;
    /**
     * Starts a JDWP tracker for the given device.
     *
     * Note that as the tracker will keep a connection open, you must call `tracker.end()` if you wish to stop tracking JDWP processes.
     *
     * @returns The JDWP tracker, which is an [`EventEmitter`][node-events]. The following events are available:
     *  -   **add** **(pid)** Emitted when a new JDWP process becomes available, once per pid.
     *  -   **remove** **(pid)** Emitted when a JDWP process becomes unavailable, once per pid.
     *  -   **changeSet** **(changes, pids)** All changes in a single event.
     *    -   **changes** An object with the following properties always present:
     *      -   **added** An array of pids that were added. Empty if none.
     *      -   **removed** An array of pids that were removed. Empty if none.
     *    -   **pids** All currently active pids (including pids from previous runs).
     *  -   **end** Emitted when the underlying connection ends.
     *  -   **error** **(err)** Emitted if there's an error.
     */
    trackJdwp(): Promise<JdwpTracker>;
    /**
     * Fetches the current **raw** framebuffer (i.e. what is visible on the screen) from the device, and optionally converts it into something more usable by using [GraphicsMagick][graphicsmagick]'s `gm` command, which must be available in `$PATH` if conversion is desired. Note that we don't bother supporting really old framebuffer formats such as RGB_565. If for some mysterious reason you happen to run into a `>=2.3` device that uses RGB_565, let us know.
     *
     * Note that high-resolution devices can have quite massive framebuffers. For example, a device with a resolution of 1920x1080 and 32 bit colors would have a roughly 8MB (`1920*1080*4` byte) RGBA framebuffer. Empirical tests point to about 5MB/s bandwidth limit for the ADB USB connection, which means that it can take ~1.6 seconds for the raw data to arrive, or even more if the USB connection is already congested. Using a conversion will further slow down completion.
     *
     * @param format The desired output format. Any output format supported by [GraphicsMagick][graphicsmagick] (such as `'png'`) is supported. Defaults to `'raw'` for raw framebuffer data.
     *
     * @returns The possibly converted framebuffer stream. The stream also has a `meta`.:
     */
    framebuffer(format?: string): Promise<FramebufferStreamWithMeta>;
    /**
     * Takes a screenshot in PNG format using the built-in `screencap` utility. This is analogous to `adb shell screencap -p`. Sadly, the utility is not available on most Android `<=2.3` devices, but a silent fallback to the `client.framebuffer()` command in PNG mode is attempted, so you should have its dependencies installed just in case.
     *
     * Generating the PNG on the device naturally requires considerably more processing time on that side. However, as the data transferred over USB easily decreases by ~95%, and no conversion being required on the host, this method is usually several times faster than using the framebuffer. Naturally, this benefit does not apply if we're forced to fall back to the framebuffer.
     *
     * For convenience purposes, if the screencap command fails (e.g. because it doesn't exist on older Androids), we fall back to `client.framebuffer(serial, 'png')`, which is slower and has additional installation requirements.
     *
     * @return The PNG stream.
     */
    screencap(): Promise<Duplex>;
    /**
     * Opens a direct connection to a unix domain socket in the given path.
     *
     * @param path The path to the socket. Prefixed with `'localfilesystem:'` by default, include another prefix (e.g. `'localabstract:'`) in the path to override.
     *
     * @returns The connection (i.e. [`net.Socket`][node-net]). Read and write as you please. Call `conn.end()` to end the connection.
     */
    openLocal(path: string): Promise<Duplex>;
    /**
     * Testing only
     */
    openLocal2(path: string, debugCtxt?: string): Promise<PromiseDuplex<Duplex>>;
    /**
     * Opens a direct connection to a binary log file, providing access to the raw log data. Note that it is usually much more convenient to use the `client.openLogcat()` method, described separately.
     *
     * @param name The name of the log. Available logs include `'main'`, `'system'`, `'radio'` and `'events'`.
     *
     * @returns The binary log stream. Call `log.end()` when you wish to stop receiving data.
     */
    openLog(name: string): Promise<Duplex>;
    /**
       * Opens a direct TCP connection to a port on the device, without any port forwarding required.
  
       * @param port The port number to connect to.
       * @param host Optional. The host to connect to. Allegedly this is supposed to establish a connection to the given host from the device, but we have not been able to get it to work at all. Skip the host and everything works great.
       *
       * @returns The TCP connection (i.e. [`net.Socket`][node-net]). Read and write as you please. Call `conn.end()` to end the connection.
       */
    openTcp(port: number, host?: string): Promise<Duplex>;
    /**
     * Starts the built-in `monkey` utility on the device, connects to it using `client.openTcp()` and hands the connection to [adbkit-monkey][adbkit-monkey], a pure Node.js Monkey client. This allows you to create touch and key events, among other things.
     *
     * For more information, check out the [adbkit-monkey][adbkit-monkey] documentation.
     *
     * @param port Optional. The device port where you'd like Monkey to run at. Defaults to `1080`.
     *
     * @returns The Monkey client. Please see the [adbkit-monkey][adbkit-monkey] documentation for details.
     */
    openMonkey(port?: number): Promise<MonkeyClient>;
    /**
     * Calls the `logcat` utility on the device and hands off the connection to [adbkit-logcat][adbkit-logcat], a pure Node.js Logcat client. This is analogous to `adb logcat -B`, but the event stream will be parsed for you and a separate event will be emitted for every log entry, allowing for easy processing.
     *
     * For more information, check out the [adbkit-logcat][adbkit-logcat] documentation.
     *
     * @param options Optional. The following options are supported:
     * -   **clear** When `true`, clears logcat before opening the reader. Not set by default.
     *
     * @returns The Logcat client. Please see the [adbkit-logcat][adbkit-logcat] documentation for details.
     */
    openLogcat(options?: {
        clear?: boolean;
    }): Promise<Logcat>;
    /**
     * Tracks `/proc/stat` and emits useful information, such as CPU load.
     * A single sync service instance is used to download the `/proc/stat` file for processing.
     * While doing this does consume some resources, it is very light and should not be a problem.
     * /proc/stat is pulled once per sec, and emit a 'load' event.
     *
     * @returns The `/proc/stat` tracker, which is an [`EventEmitter`][node-events]. Call `stat.end()` to stop tracking. The following events are available:
     *   -   **load** **(loads)** Emitted when a CPU load calculation is available.
     *   -   **loads** CPU loads of **online** CPUs. Each key is a CPU id (e.g. `'cpu0'`, `'cpu1'`) and the value an object with the following properties:
     *     -   **user** Percentage (0-100) of ticks spent on user programs.
     *     -   **nice** Percentage (0-100) of ticks spent on `nice`d user programs.
     *     -   **system** Percentage (0-100) of ticks spent on system programs.
     *     -   **idle** Percentage (0-100) of ticks spent idling.
     *     -   **iowait** Percentage (0-100) of ticks spent waiting for IO.
     *     -   **irq** Percentage (0-100) of ticks spent on hardware interrupts.
     *     -   **softirq** Percentage (0-100) of ticks spent on software interrupts.
     *     -   **steal** Percentage (0-100) of ticks stolen by others.
     *     -   **guest** Percentage (0-100) of ticks spent by a guest.
     *     -   **guestnice** Percentage (0-100) of ticks spent by a `nice`d guest.
     *     -   **total** Total. Always 100.
     */
    openProcStat(): Promise<ProcStat>;
    /**
     * Deletes all data associated with a package from the device. This is roughly analogous to `adb shell pm clear <pkg>`.
     *
     * @param pkg The package name. This is NOT the APK.
     *
     * @returns true
     */
    clear(pkg: string): Promise<boolean>;
    /**
     * Installs the APK on the device, replacing any previously installed version. This is roughly analogous to `adb install -r <apk>`.
     *
     * Note that if the call seems to stall, you may have to accept a dialog on the phone first.
     *
     * @param apk When `String`, interpreted as a path to an APK file. When [`Stream`][node-stream], installs directly from the stream, which must be a valid APK.
     * @returns true
     * @example
     * This example requires the [request](https://www.npmjs.org/package/request) module. It also doesn't do any error handling (404 responses, timeouts, invalid URLs etc).
     * ```ts
     * import Adb from '@u4/adbkit';
     * import request from 'request';
     * import { Readable } from 'stream';
     *
     * const client = Adb.createClient();
     *
     * const test = async () => {
     *   // The request module implements old-style streams, so we have to wrap it.
     *   try {
     *     // request is deprecated
     *     const device = client.getClient('<serial>');
     *     await device.install(new Readable().wrap(request('http://example.org/app.apk') as any) as any)
     *     console.log('Installed')
     *   } catch (err) {
     *     console.error('Something went wrong:', err.stack)
     *   }
     * }
     * ```
     * @example
     * Install an apk to all connected devices
     * ```ts
     * import Adb from '@u4/adbkit';
     *
     * const client = Adb.createClient();
     * const apk = 'vendor/app.apk';
     *
     * const test = async () => {
     *     try {
     *         const devices = await client.listDevices();
     *         for (const device of devices) {
     *             await device.getClient().install(apk);
     *             console.log(`Installed ${apk} on all connected devices`);
     *         }
     *     } catch (err) {
     *         console.error('Something went wrong:', err.stack);
     *     }
     * };
     * ```
     */
    install(apk: string | ReadStream): Promise<boolean>;
    /**
     * Installs an APK file which must already be located on the device file system, and replaces any previously installed version. Useful if you've previously pushed the file to the device for some reason (perhaps to have direct access to `client.push()`'s transfer stats). This is roughly analogous to `adb shell pm install -r <apk>` followed by `adb shell rm -f <apk>`.
     *
     * Note that if the call seems to stall, you may have to accept a dialog on the phone first.
     *
     * @param apk The path to the APK file on the device. The file will be removed when the command completes.
     * @returns true
     */
    installRemote(apk: string): Promise<boolean>;
    /**
     * Uninstalls the package from the device. This is roughly analogous to `adb uninstall <pkg>`.
     *
     * @param pkg The package name. This is NOT the APK.
     * @returns true
     */
    uninstall(pkg: string, opts?: hostCmd.UninstallCommandOptions): Promise<boolean>;
    /**
     * Tells you if the specific package is installed or not. This is analogous to `adb shell pm path <pkg>` and some output parsing.
     *
     * @param pkg The package name. This is NOT the APK.
     *
     * @returns `true` if the package is installed, `false` otherwise.
     */
    isInstalled(pkg: string): Promise<boolean>;
    /**
     * Starts the configured activity on the device. Roughly analogous to `adb shell am start <options>`.
     *
     * @param options The activity configuration.
     */
    startActivity(options: StartActivityOptions): Promise<boolean>;
    /**
     * Starts the configured service on the device. Roughly analogous to `adb shell am startservice <options>`.
     * @param options The activity configuration.
     */
    startService(options: StartServiceOptions): Promise<boolean>;
    /**
     * Establishes a new Sync connection that can be used to push and pull files. This method provides the most freedom and the best performance for repeated use, but can be a bit cumbersome to use. For simple use cases, consider using `client.stat()`, `client.push()` and `client.pull()`.
     *
     * @returns The Sync client. See below for details. Call `sync.end()` when done.
     */
    syncService(): Promise<Sync>;
    /**
      * A convenience shortcut for `sync.stat()`, mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.
      *
      * @param path The path.
      *
      * @returns An [`fs.Stats`][node-fs-stats] instance. While the `stats.is*` methods are available, only the following properties are supported:
      *  -   **mode** The raw mode.
      *  -   **size** The file size.
      *  -   **mtime** The time of last modification as a `Date`.
      */
    stat(path: string): Promise<Stats>;
    /**
      * A convenience shortcut for `sync.stat64()`, mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.
       *
       * @param path The path.
       *
       * @returns An [`fs.Stats`][node-fs-stats] instance. While the `stats.is*` methods are available, only the following properties are supported:
       *  -   **mode** The raw mode.
       *  -   **size** The file size.
       *  -   **mtime** The time of last modification as a `Date`.
       */
    stat64(path: string): Promise<Stats64>;
    /**
     * A convenience shortcut for `sync.readdir()`, mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.
     *
     * @param path See `sync.readdir()` for details.
     * @returns Files Lists
     * @example
     * List files in a folder
     * ```ts
     * import Bluebird from 'bluebird';
     * import Adb from '@u4/adbkit';
     * const client = Adb.createClient();
     *
     * const test = async () => {
     *     try {
     *         const devices = await client.listDevices();
     *         await Bluebird.map(devices, async (device) => {
     *             const files = await client.readdir(device.id, '/sdcard');
     *             // Synchronous, so we don't have to care about returning at the
     *             // right time
     *             files.forEach((file) => {
     *                 if (file.isFile()) {
     *                     console.log(`[${device.id}] Found file "${file.name}"`);
     *                 }
     *             });
     *         });
     *         console.log('Done checking /sdcard files on connected devices');
     *     } catch (err) {
     *         console.error('Something went wrong:', err.stack);
     *     }
     * };
     * ```
     */
    readdir(path: string): Promise<Entry[]>;
    /**
     * A convenience shortcut for `sync.readdir2()`, mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.
     *
     * @param path See `sync.readdir()` for details.
     * @returns Files Lists
     */
    readdir64(path: string): Promise<Entry64[]>;
    /**
     * A convenience shortcut for `sync.pull()`, mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.
     *
     * @param path See `sync.pull()` for details.
     *
     * @returns A `PullTransfer` instance.
     *
     * @example
     * Pulling a file from all cofnnected devices
     * ```ts
     * import Bluebird from 'bluebird';
     * import fs from 'fs';
     * import Adb from '@u4/adbkit';
     * const client = Adb.createClient();
     *
     * const test = async () => {
     *     try {
     *         const devices = await client.listDevices();
     *         await Bluebird.map(devices, async (device) => {
     *             const transfer = await client.pull(device.id, '/system/build.prop');
     *             const fn = `/tmp/${device.id}.build.prop`;
     *             await new Bluebird((resolve, reject) => {
     *                 transfer.on('progress', (stats) =>
     *                     console.log(`[${device.id}] Pulled ${stats.bytesTransferred} bytes so far`),
     *                 );
     *                 transfer.on('end', () => {
     *                     console.log(`[${device.id}] Pull complete`);
     *                     resolve(device.id);
     *                 });
     *                 transfer.on('error', reject);
     *                 transfer.pipe(fs.createWriteStream(fn));
     *             });
     *         });
     *         console.log('Done pulling /system/build.prop from all connected devices');
     *     } catch (err) {
     *         console.error('Something went wrong:', err.stack);
     *     }
     * };
     * ```
     */
    pull(path: string): Promise<PullTransfer>;
    /**
     * A convenience shortcut for `sync.push()`, mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.
     *
     * @param contents See `sync.push()` for details.
     * @param path See `sync.push()` for details.
     * @param mode See `sync.push()` for details.
     *
     * @example
     * Pushing a file to all connected devices
     * ```ts
     * import Bluebird from 'bluebird';
     * import Adb from '@u4/adbkit';
     * const client = Adb.createClient();
     *
     * const test = async () => {
     *     try {
     *         const devices = await client.listDevices();
     *         await Bluebird.map(devices, async (device) => {
     *             const transfer = await client.push(device.id, 'temp/foo.txt', '/data/local/tmp/foo.txt');
     *             await new Bluebird(function (resolve, reject) {
     *                 transfer.on('progress', (stats) =>
     *                     console.log(`[${device.id}] Pushed ${stats.bytesTransferred} bytes so far`),
     *                 );
     *                 transfer.on('end', () => {
     *                     console.log('[${device.id}] Push complete');
     *                     resolve();
     *                 });
     *                 transfer.on('error', reject);
     *             });
     *         });
     *         console.log('Done pushing foo.txt to all connected devices');
     *     } catch (err) {
     *         console.error('Something went wrong:', err.stack);
     *     }
     * };
     * ```
     */
    push(contents: string | ReadStream, path: string, mode?: number): Promise<PushTransfer>;
    /**
     * Puts the device's ADB daemon into tcp mode, allowing you to use `adb connect` or `client.connect()` to connect to it. Note that the device will still be visible to ADB as a regular USB-connected device until you unplug it. Same as `adb tcpip <port>`.
     *
     * @param port Optional. The port the device should listen on. Defaults to `5555`.
     * @returns The port the device started listening on.
     */
    tcpip(port?: number): Promise<number>;
    /**
     * Puts the device's ADB daemon back into USB mode. Reverses `client.tcpip()`. Same as `adb usb`.
     *
     * @returns true
     */
    usb(): Promise<boolean>;
    /**
     * Waits until the device has finished booting. Note that the device must already be seen by ADB. This is roughly analogous to periodically checking `adb shell getprop sys.boot_completed`.
     *
     * @returns true
     */
    waitBootComplete(): Promise<boolean>;
    /**
     * Waits until ADB can see the device. Note that you must know the serial in advance. Other than that, works like `adb -s serial wait-for-device`. If you're planning on reacting to random devices being plugged in and out, consider using `client.trackDevices()` instead.
     *
     * @returns The device ID. Can be useful for chaining.
     */
    waitForDevice(): Promise<string>;
    /**
     * prepare a Scrcpy server
     * this server must be started with the start() method
     */
    scrcpy(options?: Partial<ScrcpyOptions>): Scrcpy;
    /**
     * prepare a minicap server
     * this server must be started with the start() method
     */
    minicap(options?: Partial<MinicapOptions>): Minicap;
    /**
     * prepare a STFService and STFagent
     * this server must be started with the start() method
     */
    STFService(options?: Partial<STFServiceOptions>): STFService;
    /**
     * get extra fucntions
     * @returns an DeviceClientExtra
     */
    get extra(): DeviceClientExtra;
    /**
     * List package installed into the devices,
     * @param options list all or only third party apps
     * @returns an array of DevicePackage
     */
    listPackages(options?: {
        thirdparty?: boolean;
    }): Promise<DevicePackage[]>;
}
//# sourceMappingURL=DeviceClient.d.ts.map