From 3f61f44904569e512ee19333dc1ad17cc8d31ab1 Mon Sep 17 00:00:00 2001 From: wherewhere Date: Thu, 1 Feb 2024 20:31:03 +0800 Subject: [PATCH 1/6] Change DnsEndPoint and HashCode to internal --- .../AdbClientTests.Async.cs | 20 ++-- .../AdbClientTests.cs | 20 ++-- .../Dummys/DummyAdbClient.cs | 12 +-- AdvancedSharpAdbClient/AdbClient.Async.cs | 21 ++-- AdvancedSharpAdbClient/AdbClient.cs | 21 ++-- .../AdvancedSharpAdbClient.csproj | 8 +- .../Extensions/AdbClientExtensions.Async.cs | 96 +++++++++++++++---- .../Extensions/AdbClientExtensions.cs | 89 +++++++++++++---- .../Interfaces/IAdbClient.Async.cs | 15 +-- .../Interfaces/IAdbClient.cs | 15 +-- .../Polyfills/DnsEndPoint.cs | 11 ++- AdvancedSharpAdbClient/Polyfills/HashCode.cs | 7 +- 12 files changed, 234 insertions(+), 101 deletions(-) diff --git a/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs b/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs index b997dbe..c571790 100644 --- a/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs +++ b/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs @@ -475,7 +475,7 @@ await RunPairAsyncTest( "114514"); /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void PairAsyncDnsEndpointTest() => @@ -512,11 +512,11 @@ public async void PairAsyncIPAddressNullTest() => _ = await Assert.ThrowsAsync(() => TestClient.PairAsync((IPAddress)null, "114514")); /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void PairAsyncDnsEndpointNullTest() => - _ = await Assert.ThrowsAsync(() => TestClient.PairAsync(null, "114514")); + _ = await Assert.ThrowsAsync(() => TestClient.PairAsync((DnsEndPoint)null, "114514")); /// /// Tests the method. @@ -542,7 +542,7 @@ await RunConnectAsyncTest( "127.0.0.1:5555"); /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void ConnectAsyncDnsEndpointTest() => @@ -560,7 +560,7 @@ await RunConnectAsyncTest( "127.0.0.1:4321"); /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void ConnectAsyncHostEndpointTest() => @@ -576,11 +576,11 @@ public async void ConnectAsyncIPAddressNullTest() => _ = await Assert.ThrowsAsync(() => TestClient.ConnectAsync((IPAddress)null)); /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void ConnectAsyncDnsEndpointNullTest() => - _ = await Assert.ThrowsAsync(() => TestClient.ConnectAsync(null)); + _ = await Assert.ThrowsAsync(() => TestClient.ConnectAsync((DnsEndPoint)null)); /// /// Tests the method. @@ -590,14 +590,14 @@ public async void ConnectAsyncIPEndpointNullTest() => _ = await Assert.ThrowsAsync(() => TestClient.ConnectAsync((IPEndPoint)null)); /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void ConnectAsyncHostEndpointNullTest() => - _ = await Assert.ThrowsAsync(() => TestClient.ConnectAsync((string)null)); + _ = await Assert.ThrowsAsync(() => TestClient.ConnectAsync(null)); /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void DisconnectAsyncTest() diff --git a/AdvancedSharpAdbClient.Tests/AdbClientTests.cs b/AdvancedSharpAdbClient.Tests/AdbClientTests.cs index f8adc8d..9f170a9 100644 --- a/AdvancedSharpAdbClient.Tests/AdbClientTests.cs +++ b/AdvancedSharpAdbClient.Tests/AdbClientTests.cs @@ -597,7 +597,7 @@ public void PairIPAddressTest() => "114514"); /// - /// Tests the method. + /// Tests the method. /// [Fact] public void PairDnsEndpointTest() => @@ -634,11 +634,11 @@ public void PairIPAddressNullTest() => _ = Assert.Throws(() => TestClient.Pair((IPAddress)null, "114514")); /// - /// Tests the method. + /// Tests the method. /// [Fact] public void PairDnsEndpointNullTest() => - _ = Assert.Throws(() => TestClient.Pair(null, "114514")); + _ = Assert.Throws(() => TestClient.Pair((DnsEndPoint)null, "114514")); /// /// Tests the method. @@ -664,7 +664,7 @@ public void ConnectIPAddressTest() => "127.0.0.1:5555"); /// - /// Tests the method. + /// Tests the method. /// [Fact] public void ConnectDnsEndpointTest() => @@ -682,7 +682,7 @@ public void ConnectIPEndpointTest() => "127.0.0.1:4321"); /// - /// Tests the method. + /// Tests the method. /// [Fact] public void ConnectHostEndpointTest() => @@ -698,11 +698,11 @@ public void ConnectIPAddressNullTest() => _ = Assert.Throws(() => TestClient.Connect((IPAddress)null)); /// - /// Tests the method. + /// Tests the method. /// [Fact] public void ConnectDnsEndpointNullTest() => - _ = Assert.Throws(() => TestClient.Connect(null)); + _ = Assert.Throws(() => TestClient.Connect((DnsEndPoint)null)); /// /// Tests the method. @@ -712,14 +712,14 @@ public void ConnectIPEndpointNullTest() => _ = Assert.Throws(() => TestClient.Connect((IPEndPoint)null)); /// - /// Tests the method. + /// Tests the method. /// [Fact] public void ConnectHostEndpointNullTest() => - _ = Assert.Throws(() => TestClient.Connect((string)null)); + _ = Assert.Throws(() => TestClient.Connect(null)); /// - /// Tests the method. + /// Tests the method. /// [Fact] public void DisconnectTest() diff --git a/AdvancedSharpAdbClient.Tests/Dummys/DummyAdbClient.cs b/AdvancedSharpAdbClient.Tests/Dummys/DummyAdbClient.cs index 5435cf6..606c4d6 100644 --- a/AdvancedSharpAdbClient.Tests/Dummys/DummyAdbClient.cs +++ b/AdvancedSharpAdbClient.Tests/Dummys/DummyAdbClient.cs @@ -202,9 +202,9 @@ public IAsyncEnumerable ExecuteServerCommandAsync(string target, string #region Not Implemented - string IAdbClient.Connect(DnsEndPoint endpoint) => throw new NotImplementedException(); + string IAdbClient.Connect(string host, int port) => throw new NotImplementedException(); - Task IAdbClient.ConnectAsync(DnsEndPoint endpoint, CancellationToken cancellationToken) => throw new NotImplementedException(); + Task IAdbClient.ConnectAsync(string host, int port, CancellationToken cancellationToken) => throw new NotImplementedException(); int IAdbClient.CreateForward(DeviceData device, string local, string remote, bool allowRebind) => throw new NotImplementedException(); @@ -216,9 +216,9 @@ public IAsyncEnumerable ExecuteServerCommandAsync(string target, string Task IAdbClient.CreateReverseForwardAsync(DeviceData device, string remote, string local, bool allowRebind, CancellationToken cancellationToken) => throw new NotImplementedException(); - string IAdbClient.Disconnect(DnsEndPoint endpoint) => throw new NotImplementedException(); + string IAdbClient.Disconnect(string host, int port) => throw new NotImplementedException(); - Task IAdbClient.DisconnectAsync(DnsEndPoint endpoint, CancellationToken cancellationToken) => throw new NotImplementedException(); + Task IAdbClient.DisconnectAsync(string host, int port, CancellationToken cancellationToken) => throw new NotImplementedException(); int IAdbClient.GetAdbVersion() => throw new NotImplementedException(); @@ -276,9 +276,9 @@ public IAsyncEnumerable ExecuteServerCommandAsync(string target, string Task> IAdbClient.ListReverseForwardAsync(DeviceData device, CancellationToken cancellationToken) => throw new NotImplementedException(); - string IAdbClient.Pair(DnsEndPoint endpoint, string code) => throw new NotImplementedException(); + string IAdbClient.Pair(string host, int port, string code) => throw new NotImplementedException(); - Task IAdbClient.PairAsync(DnsEndPoint endpoint, string code, CancellationToken cancellationToken) => throw new NotImplementedException(); + Task IAdbClient.PairAsync(string host, int port, string code, CancellationToken cancellationToken) => throw new NotImplementedException(); void IAdbClient.Reboot(string into, DeviceData device) => throw new NotImplementedException(); diff --git a/AdvancedSharpAdbClient/AdbClient.Async.cs b/AdvancedSharpAdbClient/AdbClient.Async.cs index 3b509f7..9df43e6 100644 --- a/AdvancedSharpAdbClient/AdbClient.Async.cs +++ b/AdvancedSharpAdbClient/AdbClient.Async.cs @@ -453,36 +453,39 @@ public virtual async Task RebootAsync(string into, DeviceData device, Cancellati } /// - public virtual async Task PairAsync(DnsEndPoint endpoint, string code, CancellationToken cancellationToken = default) + public virtual async Task PairAsync(string host, int port, string code, CancellationToken cancellationToken = default) { - ExceptionExtensions.ThrowIfNull(endpoint); + ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - await socket.SendAdbRequestAsync($"host:pair:{code}:{endpoint.Host}:{endpoint.Port}", cancellationToken).ConfigureAwait(false); + string address = host.Contains(":") ? host : $"{host}:{port}"; + await socket.SendAdbRequestAsync($"host:pair:{code}:{address}", cancellationToken).ConfigureAwait(false); _ = await socket.ReadAdbResponseAsync(cancellationToken).ConfigureAwait(false); return await socket.ReadStringAsync(cancellationToken).ConfigureAwait(false); } /// - public virtual async Task ConnectAsync(DnsEndPoint endpoint, CancellationToken cancellationToken = default) + public virtual async Task ConnectAsync(string host, int port = DefaultPort, CancellationToken cancellationToken = default) { - ExceptionExtensions.ThrowIfNull(endpoint); + ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - await socket.SendAdbRequestAsync($"host:connect:{endpoint.Host}:{endpoint.Port}", cancellationToken).ConfigureAwait(false); + string address = host.Contains(":") ? host : $"{host}:{port}"; + await socket.SendAdbRequestAsync($"host:connect:{address}", cancellationToken).ConfigureAwait(false); _ = await socket.ReadAdbResponseAsync(cancellationToken).ConfigureAwait(false); return await socket.ReadStringAsync(cancellationToken).ConfigureAwait(false); } /// - public virtual async Task DisconnectAsync(DnsEndPoint endpoint, CancellationToken cancellationToken = default) + public virtual async Task DisconnectAsync(string host, int port = DefaultPort, CancellationToken cancellationToken = default) { - ExceptionExtensions.ThrowIfNull(endpoint); + ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - await socket.SendAdbRequestAsync($"host:disconnect:{endpoint.Host}:{endpoint.Port}", cancellationToken).ConfigureAwait(false); + string address = host.Contains(":") ? host : $"{host}:{port}"; + await socket.SendAdbRequestAsync($"host:disconnect:{address}", cancellationToken).ConfigureAwait(false); _ = await socket.ReadAdbResponseAsync(cancellationToken).ConfigureAwait(false); return await socket.ReadStringAsync(cancellationToken).ConfigureAwait(false); diff --git a/AdvancedSharpAdbClient/AdbClient.cs b/AdvancedSharpAdbClient/AdbClient.cs index 0e4ec19..580f018 100644 --- a/AdvancedSharpAdbClient/AdbClient.cs +++ b/AdvancedSharpAdbClient/AdbClient.cs @@ -591,36 +591,39 @@ public virtual void Reboot(string into, DeviceData device) } /// - public virtual string Pair(DnsEndPoint endpoint, string code) + public virtual string Pair(string host, int port, string code) { - ExceptionExtensions.ThrowIfNull(endpoint); + ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - socket.SendAdbRequest($"host:pair:{code}:{endpoint.Host}:{endpoint.Port}"); + string address = host.Contains(":") ? host : $"{host}:{port}"; + socket.SendAdbRequest($"host:pair:{address}:{port}"); _ = socket.ReadAdbResponse(); return socket.ReadString(); } /// - public virtual string Connect(DnsEndPoint endpoint) + public virtual string Connect(string host, int port = DefaultPort) { - ExceptionExtensions.ThrowIfNull(endpoint); + ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - socket.SendAdbRequest($"host:connect:{endpoint.Host}:{endpoint.Port}"); + string address = host.Contains(":") ? host : $"{host}:{port}"; + socket.SendAdbRequest($"host:connect:{address}"); _ = socket.ReadAdbResponse(); return socket.ReadString(); } /// - public virtual string Disconnect(DnsEndPoint endpoint) + public virtual string Disconnect(string host, int port = DefaultPort) { - ExceptionExtensions.ThrowIfNull(endpoint); + ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - socket.SendAdbRequest($"host:disconnect:{endpoint.Host}:{endpoint.Port}"); + string address = host.Contains(":") ? host : $"{host}:{port}"; + socket.SendAdbRequest($"host:disconnect:{address}"); _ = socket.ReadAdbResponse(); return socket.ReadString(); diff --git a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj index 6a5e842..d93617f 100644 --- a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj +++ b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj @@ -118,6 +118,12 @@ $(DefineConstants);HAS_TASK + + $(DefineConstants);HAS_DRAWING + + - $(DefineConstants);HAS_PROCESS;HAS_DRAWING;HAS_SERIALIZATION + $(DefineConstants);HAS_PROCESS;HAS_SERIALIZATION diff --git a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs index a0a9fb4..cf76760 100644 --- a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs +++ b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs @@ -289,7 +289,7 @@ public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, public static Task PairAsync(this IAdbClient client, IPAddress address, string code, CancellationToken cancellationToken = default) => address == null ? throw new ArgumentNullException(nameof(address)) - : client.PairAsync(new IPEndPoint(address, AdbClient.DefaultPort), code, cancellationToken); + : client.PairAsync(address.ToString(), AdbClient.DefaultPort, code, cancellationToken); /// /// Asynchronously pair with a device for secure TCP/IP communication. @@ -302,7 +302,7 @@ public static Task PairAsync(this IAdbClient client, IPAddress address, public static Task PairAsync(this IAdbClient client, IPEndPoint endpoint, string code, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) - : client.PairAsync(new DnsEndPoint(endpoint.Address.ToString(), endpoint.Port), code, cancellationToken); + : client.PairAsync(endpoint.Address.ToString(), endpoint.Port, code, cancellationToken); /// /// Asynchronously pair with a device for secure TCP/IP communication. @@ -313,54 +313,75 @@ public static Task PairAsync(this IAdbClient client, IPEndPoint endpoint /// A which can be used to cancel the asynchronous operation. /// The results from adb. public static Task PairAsync(this IAdbClient client, string host, string code, CancellationToken cancellationToken = default) => - client.PairAsync(Extensions.CreateDnsEndPoint(host, AdbClient.DefaultPort), code, cancellationToken); + client.PairAsync(host, AdbClient.DefaultPort, code, cancellationToken); /// - /// Asynchronously pair with a device for secure TCP/IP communication. + /// Asynchronously connect to a device via TCP/IP. + /// + /// An instance of a class that implements the interface. + /// The IP address of the remote device. + /// A which can be used to cancel the asynchronous operation. + /// A which returns the results from adb. + public static Task ConnectAsync(this IAdbClient client, IPAddress address, CancellationToken cancellationToken = default) => + address == null + ? throw new ArgumentNullException(nameof(address)) + : client.ConnectAsync(address.ToString(), AdbClient.DefaultPort, cancellationToken); + + /// + /// Asynchronously connect to a device via TCP/IP. + /// + /// An instance of a class that implements the interface. + /// The IP endpoint at which the adb server on the device is running. + /// A which can be used to cancel the asynchronous operation. + /// A which returns the results from adb. + public static Task ConnectAsync(this IAdbClient client, IPEndPoint endpoint, CancellationToken cancellationToken = default) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.ConnectAsync(endpoint.Address.ToString(), endpoint.Port, cancellationToken); + + /// + /// Asynchronously connect to a device via TCP/IP. /// /// An instance of a class that implements the interface. /// The host address of the remote device. - /// The port of the remote device. - /// The pairing code. /// A which can be used to cancel the asynchronous operation. /// The results from adb. - public static Task PairAsync(this IAdbClient client, string host, int port, string code, CancellationToken cancellationToken = default) => - client.PairAsync(Extensions.CreateDnsEndPoint(host, port), code, cancellationToken); + public static Task ConnectAsync(this IAdbClient client, string host, CancellationToken cancellationToken = default) => + client.ConnectAsync(host, AdbClient.DefaultPort, cancellationToken); /// - /// Asynchronously connect to a device via TCP/IP. + /// Asynchronously disconnects a remote device from this local ADB server. /// /// An instance of a class that implements the interface. /// The IP address of the remote device. /// A which can be used to cancel the asynchronous operation. /// A which returns the results from adb. - public static Task ConnectAsync(this IAdbClient client, IPAddress address, CancellationToken cancellationToken = default) => + public static Task DisconnectAsync(this IAdbClient client, IPAddress address, CancellationToken cancellationToken = default) => address == null ? throw new ArgumentNullException(nameof(address)) - : client.ConnectAsync(new IPEndPoint(address, AdbClient.DefaultPort), cancellationToken); + : client.DisconnectAsync(address.ToString(), AdbClient.DefaultPort, cancellationToken); /// - /// Asynchronously connect to a device via TCP/IP. + /// Asynchronously disconnects a remote device from this local ADB server. /// /// An instance of a class that implements the interface. /// The IP endpoint at which the adb server on the device is running. /// A which can be used to cancel the asynchronous operation. /// A which returns the results from adb. - public static Task ConnectAsync(this IAdbClient client, IPEndPoint endpoint, CancellationToken cancellationToken = default) => + public static Task DisconnectAsync(this IAdbClient client, IPEndPoint endpoint, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) - : client.ConnectAsync(new DnsEndPoint(endpoint.Address.ToString(), endpoint.Port), cancellationToken); + : client.DisconnectAsync(endpoint.Address.ToString(), endpoint.Port, cancellationToken); /// - /// Asynchronously connect to a device via TCP/IP. + /// Asynchronously disconnects a remote device from this local ADB server. /// /// An instance of a class that implements the interface. /// The host address of the remote device. - /// The port of the remote device. /// A which can be used to cancel the asynchronous operation. - /// A which returns the results from adb. - public static Task ConnectAsync(this IAdbClient client, string host, int port = AdbClient.DefaultPort, CancellationToken cancellationToken = default) => - client.ConnectAsync(Extensions.CreateDnsEndPoint(host, port), cancellationToken); + /// The results from adb. + public static Task DisconnectAsync(this IAdbClient client, string host, CancellationToken cancellationToken = default) => + client.DisconnectAsync(host, AdbClient.DefaultPort, cancellationToken); #if !NETFRAMEWORK || NET40_OR_GREATER /// @@ -444,6 +465,43 @@ public static Task InstallMultipleAsync(this IAdbClient client, DeviceData devic /// A which represents the asynchronous operation. public static Task InstallWriteAsync(this IAdbClient client, DeviceData device, Stream apk, string apkName, string session, IProgress? progress = null, CancellationToken cancellationToken = default) => client.InstallWriteAsync(device, apk, apkName, session, progress.AsAction(), cancellationToken); + + /// + /// Asynchronously pair with a device for secure TCP/IP communication. + /// + /// An instance of a class that implements the interface. + /// The DNS endpoint at which the adb server on the device is running. + /// The pairing code. + /// A which can be used to cancel the asynchronous operation. + /// The results from adb. + public static Task PairAsync(this IAdbClient client, DnsEndPoint endpoint, string code, CancellationToken cancellationToken = default) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.PairAsync(endpoint.Host, endpoint.Port, code, cancellationToken); + + /// + /// Asynchronously connect to a device via TCP/IP. + /// + /// An instance of a class that implements the interface. + /// The DNS endpoint at which the adb server on the device is running. + /// A which can be used to cancel the asynchronous operation. + /// A which returns the results from adb. + public static Task ConnectAsync(this IAdbClient client, DnsEndPoint endpoint, CancellationToken cancellationToken = default) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.ConnectAsync(endpoint.Host, endpoint.Port, cancellationToken); + + /// + /// Asynchronously disconnects a remote device from this local ADB server. + /// + /// An instance of a class that implements the interface. + /// The DNS endpoint at which the adb server on the device is running. + /// A which can be used to cancel the asynchronous operation. + /// A which returns the results from adb. + public static Task DisconnectAsync(this IAdbClient client, DnsEndPoint endpoint, CancellationToken cancellationToken = default) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.DisconnectAsync(endpoint.Host, endpoint.Port, cancellationToken); #if WINDOWS_UWP || WINDOWS10_0_17763_0_OR_GREATER /// diff --git a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs index 304468a..1b406e8 100644 --- a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs +++ b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs @@ -243,7 +243,7 @@ public static void RunLogService(this IAdbClient client, DeviceData device, Acti public static string Pair(this IAdbClient client, IPAddress address, string code) => address == null ? throw new ArgumentNullException(nameof(address)) - : client.Pair(new IPEndPoint(address, AdbClient.DefaultPort), code); + : client.Pair(address.ToString(), AdbClient.DefaultPort, code); /// /// Pair with a device for secure TCP/IP communication. @@ -255,7 +255,7 @@ public static string Pair(this IAdbClient client, IPAddress address, string code public static string Pair(this IAdbClient client, IPEndPoint endpoint, string code) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) - : client.Pair(new DnsEndPoint(endpoint.Address.ToString(), endpoint.Port), code); + : client.Pair(endpoint.Address.ToString(), endpoint.Port, code); /// /// Pair with a device for secure TCP/IP communication. @@ -265,50 +265,69 @@ public static string Pair(this IAdbClient client, IPEndPoint endpoint, string co /// The pairing code. /// The results from adb. public static string Pair(this IAdbClient client, string host, string code) => - client.Pair(Extensions.CreateDnsEndPoint(host, AdbClient.DefaultPort), code); + client.Pair(host, AdbClient.DefaultPort, code); /// - /// Pair with a device for secure TCP/IP communication. + /// Connect to a device via TCP/IP. /// /// An instance of a class that implements the interface. - /// The host address of the remote device. - /// The port of the remote device. - /// The pairing code. + /// The IP address of the remote device. + /// The results from adb. + public static string Connect(this IAdbClient client, IPAddress address) => + address == null + ? throw new ArgumentNullException(nameof(address)) + : client.Connect(address.ToString(), AdbClient.DefaultPort); + + /// + /// Connect to a device via TCP/IP. + /// + /// An instance of a class that implements the interface. + /// The IP endpoint at which the adb server on the device is running. /// The results from adb. - public static string Pair(this IAdbClient client, string host, int port, string code) => - client.Pair(Extensions.CreateDnsEndPoint(host, port), code); + public static string Connect(this IAdbClient client, IPEndPoint endpoint) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.Connect(endpoint.Address.ToString(), endpoint.Port); /// /// Connect to a device via TCP/IP. /// /// An instance of a class that implements the interface. + /// The host address of the remote device. + /// The results from adb. + public static string Connect(this IAdbClient client, string host) => + client.Connect(host, AdbClient.DefaultPort); + + /// + /// Disconnects a remote device from this local ADB server. + /// + /// An instance of a class that implements the interface. /// The IP address of the remote device. /// The results from adb. - public static string Connect(this IAdbClient client, IPAddress address) => + public static string Disconnect(this IAdbClient client, IPAddress address) => address == null ? throw new ArgumentNullException(nameof(address)) - : client.Connect(new IPEndPoint(address, AdbClient.DefaultPort)); + : client.Disconnect(address.ToString(), AdbClient.DefaultPort); /// - /// Connect to a device via TCP/IP. + /// Disconnects a remote device from this local ADB server. /// /// An instance of a class that implements the interface. /// The IP endpoint at which the adb server on the device is running. /// The results from adb. - public static string Connect(this IAdbClient client, IPEndPoint endpoint) => + public static string Disconnect(this IAdbClient client, IPEndPoint endpoint) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) - : client.Connect(new DnsEndPoint(endpoint.Address.ToString(), endpoint.Port)); + : client.Disconnect(endpoint.Address.ToString(), endpoint.Port); /// - /// Connect to a device via TCP/IP. + /// Disconnects a remote device from this local ADB server. /// /// An instance of a class that implements the interface. /// The host address of the remote device. - /// The port of the remote device. /// The results from adb. - public static string Connect(this IAdbClient client, string host, int port = AdbClient.DefaultPort) => - client.Connect(Extensions.CreateDnsEndPoint(host, port)); + public static string Disconnect(this IAdbClient client, string host) => + client.Disconnect(host, AdbClient.DefaultPort); #if !NETFRAMEWORK || NET40_OR_GREATER /// @@ -382,6 +401,40 @@ public static void InstallMultiple(this IAdbClient client, DeviceData device, IE /// The progress is reported as a value between 0 and 100, representing the percentage of the apk which has been transferred. public static void InstallWrite(this IAdbClient client, DeviceData device, Stream apk, string apkName, string session, IProgress? progress) => client.InstallWrite(device, apk, apkName, session, progress.AsAction()); + + /// + /// Pair with a device for secure TCP/IP communication. + /// + /// An instance of a class that implements the interface. + /// The DNS endpoint at which the adb server on the device is running. + /// The pairing code. + /// The results from adb. + public static string Pair(this IAdbClient client, DnsEndPoint endpoint, string code) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.Pair(endpoint.Host, endpoint.Port, code); + + /// + /// Connect to a device via TCP/IP. + /// + /// An instance of a class that implements the interface. + /// The DNS endpoint at which the adb server on the device is running. + /// The results from adb. + public static string Connect(this IAdbClient client, DnsEndPoint endpoint) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.Connect(endpoint.Host, endpoint.Port); + + /// + /// Disconnects a remote device from this local ADB server. + /// + /// An instance of a class that implements the interface. + /// The DNS endpoint at which the adb server on the device is running. + /// The results from adb. + public static string Disconnect(this IAdbClient client, DnsEndPoint endpoint) => + endpoint == null + ? throw new ArgumentNullException(nameof(endpoint)) + : client.Disconnect(endpoint.Host, endpoint.Port); #endif } } diff --git a/AdvancedSharpAdbClient/Interfaces/IAdbClient.Async.cs b/AdvancedSharpAdbClient/Interfaces/IAdbClient.Async.cs index 6be81fd..5f83294 100644 --- a/AdvancedSharpAdbClient/Interfaces/IAdbClient.Async.cs +++ b/AdvancedSharpAdbClient/Interfaces/IAdbClient.Async.cs @@ -308,27 +308,30 @@ IAsyncEnumerable RunLogServiceAsync(DeviceData device, CancellationTok /// /// Asynchronously pair with a device for secure TCP/IP communication /// - /// The DNS endpoint at which the adb server on the device is running. + /// The host address of the remote device. + /// The port of the remote device. /// The pairing code. /// A which can be used to cancel the asynchronous operation. /// A which returns the results from adb. - Task PairAsync(DnsEndPoint endpoint, string code, CancellationToken cancellationToken); + Task PairAsync(string host, int port, string code, CancellationToken cancellationToken); /// /// Asynchronously connect to a device via TCP/IP. /// - /// The DNS endpoint at which the adb server on the device is running. + /// The host address of the remote device. + /// The port of the remote device. /// A which can be used to cancel the asynchronous operation. /// A which returns the results from adb. - Task ConnectAsync(DnsEndPoint endpoint, CancellationToken cancellationToken); + Task ConnectAsync(string host, int port, CancellationToken cancellationToken); /// /// Asynchronously disconnects a remote device from this local ADB server. /// - /// The endpoint of the remote device to disconnect. + /// The host address of the remote device. + /// The port of the remote device. /// A which can be used to cancel the asynchronous operation. /// A which returns the results from adb. - Task DisconnectAsync(DnsEndPoint endpoint, CancellationToken cancellationToken); + Task DisconnectAsync(string host, int port, CancellationToken cancellationToken); /// /// Asynchronously restarts the ADB daemon running on the device with root privileges. diff --git a/AdvancedSharpAdbClient/Interfaces/IAdbClient.cs b/AdvancedSharpAdbClient/Interfaces/IAdbClient.cs index 20806fd..63751b5 100644 --- a/AdvancedSharpAdbClient/Interfaces/IAdbClient.cs +++ b/AdvancedSharpAdbClient/Interfaces/IAdbClient.cs @@ -312,24 +312,27 @@ public partial interface IAdbClient /// /// Pair with a device for secure TCP/IP communication /// - /// The DNS endpoint at which the adb server on the device is running. + /// The host address of the remote device. + /// The port of the remote device. /// The pairing code. /// The results from adb. - string Pair(DnsEndPoint endpoint, string code); + string Pair(string host, int port, string code); /// /// Connect to a device via TCP/IP. /// - /// The DNS endpoint at which the adb server on the device is running. + /// The host address of the remote device. + /// The port of the remote device. /// The results from adb. - string Connect(DnsEndPoint endpoint); + string Connect(string host, int port); /// /// Disconnects a remote device from this local ADB server. /// - /// The endpoint of the remote device to disconnect. + /// The host address of the remote device. + /// The port of the remote device. /// The results from adb. - string Disconnect(DnsEndPoint endpoint); + string Disconnect(string host, int port); /// /// Restarts the ADB daemon running on the device with root privileges. diff --git a/AdvancedSharpAdbClient/Polyfills/DnsEndPoint.cs b/AdvancedSharpAdbClient/Polyfills/DnsEndPoint.cs index 0c9e9b1..939c2fb 100644 --- a/AdvancedSharpAdbClient/Polyfills/DnsEndPoint.cs +++ b/AdvancedSharpAdbClient/Polyfills/DnsEndPoint.cs @@ -1,17 +1,18 @@ #if NETFRAMEWORK && !NET40_OR_GREATER -using System; +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -using System.Net; using System.Net.Sockets; -namespace AdvancedSharpAdbClient.Polyfills +namespace System.Net { /// /// Represents a network endpoint as a host name or a string representation of an IP address and a port number. /// [EditorBrowsable(EditorBrowsableState.Never)] - public class DnsEndPoint : EndPoint + internal class DnsEndPoint : EndPoint { private readonly AddressFamily _family; @@ -98,4 +99,6 @@ public override int GetHashCode() public int Port { get; } } } +#else +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.EndPoint))] #endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Polyfills/HashCode.cs b/AdvancedSharpAdbClient/Polyfills/HashCode.cs index 50eeeb3..b8ff0c1 100644 --- a/AdvancedSharpAdbClient/Polyfills/HashCode.cs +++ b/AdvancedSharpAdbClient/Polyfills/HashCode.cs @@ -41,13 +41,12 @@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; -namespace AdvancedSharpAdbClient.Polyfills +namespace System { // xxHash32 is used for the hash code. // https://github.com/Cyan4973/xxHash @@ -56,7 +55,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Combines the hash code for multiple values into a single hash code. /// [EditorBrowsable(EditorBrowsableState.Never)] - public struct HashCode + internal struct HashCode { private static readonly uint s_seed = GenerateGlobalSeed(); @@ -572,4 +571,6 @@ public readonly int ToHashCode() #pragma warning restore CS0809 } } +#else +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.HashCode))] #endif \ No newline at end of file From 65999f852f359ba37e0007bd41e1089c6a27b971 Mon Sep 17 00:00:00 2001 From: wherewhere Date: Thu, 1 Feb 2024 21:56:51 +0800 Subject: [PATCH 2/6] Change IReadOnlyList and IReadOnlyList to internal Change AdvancedSharpAdbClient.Polyfills.Extensions to internal --- .../Extensions/DateTimeExtensionsTests.cs | 53 ------------------- .../Extensions/DateTimeExtensions.cs | 16 +----- .../Polyfills/Extensions/EnumExtensions.cs | 2 +- .../Extensions/EnumerableExtensions.cs | 2 +- .../Extensions/ExceptionExtensions.cs | 2 +- .../Polyfills/Extensions/SocketExtensions.cs | 2 +- .../Polyfills/Extensions/StreamExtensions.cs | 2 +- .../Extensions/StringBuilderExtensions.cs | 2 +- .../Polyfills/Extensions/StringExtensions.cs | 2 +- .../Polyfills/Extensions/TaskExExtensions.cs | 2 +- .../Interfaces/IReadOnlyCollection.cs | 2 +- .../Polyfills/Interfaces/IReadOnlyList.cs | 2 +- 12 files changed, 11 insertions(+), 78 deletions(-) delete mode 100644 AdvancedSharpAdbClient.Tests/Extensions/DateTimeExtensionsTests.cs diff --git a/AdvancedSharpAdbClient.Tests/Extensions/DateTimeExtensionsTests.cs b/AdvancedSharpAdbClient.Tests/Extensions/DateTimeExtensionsTests.cs deleted file mode 100644 index e74c7fc..0000000 --- a/AdvancedSharpAdbClient.Tests/Extensions/DateTimeExtensionsTests.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using Xunit; - -namespace AdvancedSharpAdbClient.Polyfills.Tests -{ - /// - /// Tests the class. - /// - public class DateTimeExtensionsTests - { - /// - /// Tests the method. - /// - [Fact] - public void FromUnixTimeSecondsTest() - { - DateTimeOffset time = new(new DateTime(2022, 6, 1, 12, 10, 34, DateTimeKind.Utc)); - Assert.Equal(time, DateTimeExtensions.FromUnixTimeSeconds(1654085434)); - } - -#if NETFRAMEWORK && !NET46_OR_GREATER - /// - /// Tests the method. - /// - [Fact] - public void ToUnixTimeSecondsTest() - { - DateTimeOffset time = new(new DateTime(2022, 6, 1, 12, 10, 34, DateTimeKind.Utc)); - Assert.Equal(1654085434, time.ToUnixTimeSeconds()); - } -#endif - - /// - /// Tests the method. - /// - [Fact] - public void FromUnixEpochTest() - { - DateTime time = new(2022, 6, 1, 12, 10, 34, DateTimeKind.Utc); - Assert.Equal(time, DateTimeExtensions.FromUnixEpoch(1654085434)); - } - - /// - /// Tests the method. - /// - [Fact] - public void ToUnixEpochTest() - { - DateTime time = new(2022, 6, 1, 12, 10, 34, DateTimeKind.Utc); - Assert.Equal(1654085434, time.ToUnixEpoch()); - } - } -} diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/DateTimeExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/DateTimeExtensions.cs index b3d2679..d5f2305 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/DateTimeExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/DateTimeExtensions.cs @@ -11,7 +11,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides helper methods for working with Unix-based date formats. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class DateTimeExtensions + internal static class DateTimeExtensions { #if NETFRAMEWORK && !NET46_OR_GREATER // Number of 100ns ticks per time unit @@ -102,19 +102,5 @@ public static long ToUnixTimeSeconds(this DateTimeOffset dateTimeOffset) return seconds - UnixEpochSeconds; } #endif - - /// - /// Converts a Unix equivalent to the . - /// - /// The Unix equivalent to convert to the date. - /// A that represents the date. - public static DateTime FromUnixEpoch(long time) => Epoch.Add(new TimeSpan(time * 1000_0000)); - - /// - /// Converts a to the Unix equivalent. - /// - /// The date to convert to the Unix format. - /// A that represents the date, in Unix format. - public static long ToUnixEpoch(this DateTime date) => (long)Math.Round(date.ToUniversalTime().Subtract(Epoch).TotalSeconds); } } diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/EnumExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/EnumExtensions.cs index 15a423b..921a6e1 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/EnumExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/EnumExtensions.cs @@ -11,7 +11,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class EnumExtensions + internal static class EnumExtensions { /// /// Converts the string representation of the name or numeric value of one or more diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/EnumerableExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/EnumerableExtensions.cs index 6f7898a..feb3207 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/EnumerableExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/EnumerableExtensions.cs @@ -15,7 +15,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class EnumerableExtensions + internal static class EnumerableExtensions { /// /// Adds the elements of the specified collection to the end of the . diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs index b4f3a1a..dec2900 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs @@ -14,7 +14,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class ExceptionExtensions + internal static class ExceptionExtensions { /// /// Throws an if is null. diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs index c213964..d6d86b6 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs @@ -14,7 +14,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class SocketExtensions + internal static class SocketExtensions { /// /// Asynchronously receives data from a connected socket. diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/StreamExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/StreamExtensions.cs index 5a447fc..dc2704f 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/StreamExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/StreamExtensions.cs @@ -14,7 +14,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class StreamExtensions + internal static class StreamExtensions { /// /// Asynchronously reads a sequence of bytes from the current stream, advances the position diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/StringBuilderExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/StringBuilderExtensions.cs index 4dbcb82..06380d9 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/StringBuilderExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/StringBuilderExtensions.cs @@ -12,7 +12,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class StringBuilderExtensions + internal static class StringBuilderExtensions { /// /// Removes all characters from the current instance. diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs index 94967f1..b9ec276 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs @@ -13,7 +13,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class StringExtensions + internal static class StringExtensions { /// /// Indicates whether a specified string is , empty, or consists only of white-space characters. diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs index 7e4bcc5..4d30eac 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs @@ -19,7 +19,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// Provides extension methods for the class. /// [EditorBrowsable(EditorBrowsableState.Never)] - public static class TaskExExtensions + internal static class TaskExExtensions { #if NETFRAMEWORK && !NET46_OR_GREATER /// diff --git a/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyCollection.cs b/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyCollection.cs index 922a36b..5691317 100644 --- a/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyCollection.cs +++ b/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyCollection.cs @@ -12,7 +12,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// /// The type of the elements. [EditorBrowsable(EditorBrowsableState.Never)] - public interface IReadOnlyCollection : IEnumerable + internal interface IReadOnlyCollection : IEnumerable { /// /// Gets the number of elements in the collection. diff --git a/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyList.cs b/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyList.cs index 3abef33..a976562 100644 --- a/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyList.cs +++ b/AdvancedSharpAdbClient/Polyfills/Interfaces/IReadOnlyList.cs @@ -11,7 +11,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// /// The type of elements in the read-only list. [EditorBrowsable(EditorBrowsableState.Never)] - public interface IReadOnlyList : IReadOnlyCollection + internal interface IReadOnlyList : IReadOnlyCollection { /// /// Gets the element at the specified index in the read-only list. From 0fc975398ab28ebdfd0f1b3890fb30904e52de2c Mon Sep 17 00:00:00 2001 From: wherewhere Date: Thu, 1 Feb 2024 23:39:39 +0800 Subject: [PATCH 3/6] Remove some useless virtual member --- .../Dummys/TracingAdbSocket.cs | 29 ++-- AdvancedSharpAdbClient/AdbClient.Async.cs | 76 ++++----- AdvancedSharpAdbClient/AdbClient.cs | 78 ++++----- .../AdbCommandLineClient.Async.cs | 44 ++--- .../AdbCommandLineClient.cs | 79 +++++---- AdvancedSharpAdbClient/AdbServer.Async.cs | 8 +- AdvancedSharpAdbClient/AdbServer.cs | 10 +- AdvancedSharpAdbClient/AdbSocket.Async.cs | 14 +- AdvancedSharpAdbClient/AdbSocket.cs | 18 +- .../DeviceCommands/DeviceClient.Async.cs | 36 ++-- .../DeviceCommands/DeviceClient.cs | 36 ++-- .../DeviceCommands/PackageManager.Async.cs | 158 +++++++++--------- .../DeviceCommands/PackageManager.cs | 146 ++++++++-------- AdvancedSharpAdbClient/DeviceMonitor.Async.cs | 2 +- AdvancedSharpAdbClient/DeviceMonitor.cs | 2 +- AdvancedSharpAdbClient/Models/Framebuffer.cs | 20 +-- AdvancedSharpAdbClient/SyncService.Async.cs | 10 +- AdvancedSharpAdbClient/SyncService.cs | 8 +- AdvancedSharpAdbClient/TcpSocket.Async.cs | 16 +- AdvancedSharpAdbClient/TcpSocket.cs | 32 ++-- 20 files changed, 407 insertions(+), 415 deletions(-) diff --git a/AdvancedSharpAdbClient.Tests/Dummys/TracingAdbSocket.cs b/AdvancedSharpAdbClient.Tests/Dummys/TracingAdbSocket.cs index 918da2b..1146494 100644 --- a/AdvancedSharpAdbClient.Tests/Dummys/TracingAdbSocket.cs +++ b/AdvancedSharpAdbClient.Tests/Dummys/TracingAdbSocket.cs @@ -82,14 +82,14 @@ public override int Read(Span data) return read; } - public override AdbResponse ReadAdbResponse() + AdbResponse IAdbSocket.ReadAdbResponse() { Exception exception = null; AdbResponse response; try { - response = base.ReadAdbResponse(); + response = ReadAdbResponse(); } catch (AdbException ex) { @@ -137,19 +137,22 @@ public override async Task ReadStringAsync(CancellationToken cancellatio return value; } - public override void SendAdbRequest(string request) + void IAdbSocket.SendAdbRequest(string request) => SendAdbRequest(request); + public new void SendAdbRequest(string request) { Requests.Add(request); - base.SendAdbRequest(request); + SendAdbRequest(request); } - public override void SendSyncRequest(SyncCommand command, string path) + void IAdbSocket.SendSyncRequest(SyncCommand command, string path) => SendSyncRequest(command, path); + public new void SendSyncRequest(SyncCommand command, string path) { SyncRequests.Add((command, path)); - base.SendSyncRequest(command, path); + SendSyncRequest(command, path); } - public override void SendSyncRequest(SyncCommand command, int length) + void IAdbSocket.SendSyncRequest(SyncCommand command, int length) => SendSyncRequest(command, length); + public new void SendSyncRequest(SyncCommand command, int length) { StackTrace trace = new(); @@ -158,19 +161,21 @@ public override void SendSyncRequest(SyncCommand command, int length) SyncRequests.Add((command, length.ToString())); } - base.SendSyncRequest(command, length); + SendSyncRequest(command, length); } - public override SyncCommand ReadSyncResponse() + SyncCommand IAdbSocket.ReadSyncResponse() => ReadSyncResponse(); + public new SyncCommand ReadSyncResponse() { - SyncCommand response = base.ReadSyncResponse(); + SyncCommand response = ReadSyncResponse(); SyncResponses.Enqueue(response); return response; } - public override void Reconnect(bool isForce = false) + void IAdbSocket.Reconnect(bool isForce) => Reconnect(isForce); + public new void Reconnect(bool isForce) { - base.Reconnect(); + Reconnect(isForce); DidReconnect = true; } } diff --git a/AdvancedSharpAdbClient/AdbClient.Async.cs b/AdvancedSharpAdbClient/AdbClient.Async.cs index 9df43e6..12cb510 100644 --- a/AdvancedSharpAdbClient/AdbClient.Async.cs +++ b/AdvancedSharpAdbClient/AdbClient.Async.cs @@ -18,7 +18,7 @@ namespace AdvancedSharpAdbClient public partial class AdbClient { /// - public virtual async Task GetAdbVersionAsync(CancellationToken cancellationToken = default) + public async Task GetAdbVersionAsync(CancellationToken cancellationToken = default) { using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -30,7 +30,7 @@ public virtual async Task GetAdbVersionAsync(CancellationToken cancellation } /// - public virtual async Task KillAdbAsync(CancellationToken cancellationToken = default) + public async Task KillAdbAsync(CancellationToken cancellationToken = default) { using IAdbSocket socket = AdbSocketFactory(EndPoint); await socket.SendAdbRequestAsync("host:kill", cancellationToken).ConfigureAwait(false); @@ -40,7 +40,7 @@ public virtual async Task KillAdbAsync(CancellationToken cancellationToken = def } /// - public virtual async Task> GetDevicesAsync(CancellationToken cancellationToken = default) + public async Task> GetDevicesAsync(CancellationToken cancellationToken = default) { using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -53,7 +53,7 @@ public virtual async Task> GetDevicesAsync(CancellationT } /// - public virtual async Task CreateForwardAsync(DeviceData device, string local, string remote, bool allowRebind, CancellationToken cancellationToken = default) + public async Task CreateForwardAsync(DeviceData device, string local, string remote, bool allowRebind, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -69,7 +69,7 @@ public virtual async Task CreateForwardAsync(DeviceData device, string loca } /// - public virtual async Task CreateReverseForwardAsync(DeviceData device, string remote, string local, bool allowRebind, CancellationToken cancellationToken = default) + public async Task CreateReverseForwardAsync(DeviceData device, string remote, string local, bool allowRebind, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -87,7 +87,7 @@ public virtual async Task CreateReverseForwardAsync(DeviceData device, stri } /// - public virtual async Task RemoveReverseForwardAsync(DeviceData device, string remote, CancellationToken cancellationToken = default) + public async Task RemoveReverseForwardAsync(DeviceData device, string remote, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -99,7 +99,7 @@ public virtual async Task RemoveReverseForwardAsync(DeviceData device, string re } /// - public virtual async Task RemoveAllReverseForwardsAsync(DeviceData device, CancellationToken cancellationToken = default) + public async Task RemoveAllReverseForwardsAsync(DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -111,7 +111,7 @@ public virtual async Task RemoveAllReverseForwardsAsync(DeviceData device, Cance } /// - public virtual async Task RemoveForwardAsync(DeviceData device, int localPort, CancellationToken cancellationToken = default) + public async Task RemoveForwardAsync(DeviceData device, int localPort, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -121,7 +121,7 @@ public virtual async Task RemoveForwardAsync(DeviceData device, int localPort, C } /// - public virtual async Task RemoveAllForwardsAsync(DeviceData device, CancellationToken cancellationToken = default) + public async Task RemoveAllForwardsAsync(DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -131,7 +131,7 @@ public virtual async Task RemoveAllForwardsAsync(DeviceData device, Cancellation } /// - public virtual async Task> ListForwardAsync(DeviceData device, CancellationToken cancellationToken = default) + public async Task> ListForwardAsync(DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -145,7 +145,7 @@ public virtual async Task> ListForwardAsync(DeviceData } /// - public virtual async Task> ListReverseForwardAsync(DeviceData device, CancellationToken cancellationToken = default) + public async Task> ListReverseForwardAsync(DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -161,7 +161,7 @@ public virtual async Task> ListReverseForwardAsync(Devi } /// - public virtual async Task ExecuteServerCommandAsync(string target, string command, CancellationToken cancellationToken = default) + public async Task ExecuteServerCommandAsync(string target, string command, CancellationToken cancellationToken = default) { using IAdbSocket socket = AdbSocketFactory(EndPoint); await ExecuteServerCommandAsync(target, command, socket, cancellationToken); @@ -182,7 +182,7 @@ public virtual async Task ExecuteServerCommandAsync(string target, string comman } /// - public virtual async Task ExecuteRemoteCommandAsync(string command, DeviceData device, CancellationToken cancellationToken = default) + public async Task ExecuteRemoteCommandAsync(string command, DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -193,7 +193,7 @@ public virtual async Task ExecuteRemoteCommandAsync(string command, DeviceData d } /// - public virtual async Task ExecuteServerCommandAsync(string target, string command, IShellOutputReceiver? receiver, Encoding encoding, CancellationToken cancellationToken = default) + public async Task ExecuteServerCommandAsync(string target, string command, IShellOutputReceiver? receiver, Encoding encoding, CancellationToken cancellationToken = default) { ExceptionExtensions.ThrowIfNull(encoding); using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -246,7 +246,7 @@ public virtual async Task ExecuteServerCommandAsync(string target, string comman } /// - public virtual async Task ExecuteRemoteCommandAsync(string command, DeviceData device, IShellOutputReceiver? receiver, Encoding encoding, CancellationToken cancellationToken = default) + public async Task ExecuteRemoteCommandAsync(string command, DeviceData device, IShellOutputReceiver? receiver, Encoding encoding, CancellationToken cancellationToken = default) { EnsureDevice(device); ExceptionExtensions.ThrowIfNull(encoding); @@ -259,7 +259,7 @@ public virtual async Task ExecuteRemoteCommandAsync(string command, DeviceData d #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER /// - public virtual async IAsyncEnumerable ExecuteServerCommandAsync(string target, string command, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default) + public async IAsyncEnumerable ExecuteServerCommandAsync(string target, string command, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default) { ExceptionExtensions.ThrowIfNull(encoding); using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -312,7 +312,7 @@ public virtual async IAsyncEnumerable ExecuteServerCommandAsync(string t } /// - public virtual async IAsyncEnumerable ExecuteRemoteCommandAsync(string command, DeviceData device, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default) + public async IAsyncEnumerable ExecuteRemoteCommandAsync(string command, DeviceData device, Encoding encoding, [EnumeratorCancellation] CancellationToken cancellationToken = default) { EnsureDevice(device); ExceptionExtensions.ThrowIfNull(encoding); @@ -327,7 +327,7 @@ public virtual async IAsyncEnumerable ExecuteRemoteCommandAsync(string c } /// - public virtual async IAsyncEnumerable RunLogServiceAsync(DeviceData device, [EnumeratorCancellation] CancellationToken cancellationToken = default, params LogId[] logNames) + public async IAsyncEnumerable RunLogServiceAsync(DeviceData device, [EnumeratorCancellation] CancellationToken cancellationToken = default, params LogId[] logNames) { EnsureDevice(device); @@ -378,7 +378,7 @@ public virtual async IAsyncEnumerable RunLogServiceAsync(DeviceData de #endif /// - public virtual async Task RunLogServiceAsync(DeviceData device, Action messageSink, CancellationToken cancellationToken = default, params LogId[] logNames) + public async Task RunLogServiceAsync(DeviceData device, Action messageSink, CancellationToken cancellationToken = default, params LogId[] logNames) { EnsureDevice(device); ExceptionExtensions.ThrowIfNull(messageSink); @@ -429,7 +429,7 @@ public virtual async Task RunLogServiceAsync(DeviceData device, Action } /// - public virtual async Task GetFrameBufferAsync(DeviceData device, CancellationToken cancellationToken = default) + public async Task GetFrameBufferAsync(DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -441,7 +441,7 @@ public virtual async Task GetFrameBufferAsync(DeviceData device, Ca } /// - public virtual async Task RebootAsync(string into, DeviceData device, CancellationToken cancellationToken = default) + public async Task RebootAsync(string into, DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); @@ -453,12 +453,12 @@ public virtual async Task RebootAsync(string into, DeviceData device, Cancellati } /// - public virtual async Task PairAsync(string host, int port, string code, CancellationToken cancellationToken = default) + public async Task PairAsync(string host, int port, string code, CancellationToken cancellationToken = default) { ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - string address = host.Contains(":") ? host : $"{host}:{port}"; + string address = host.Contains(':') ? host : $"{host}:{port}"; await socket.SendAdbRequestAsync($"host:pair:{code}:{address}", cancellationToken).ConfigureAwait(false); _ = await socket.ReadAdbResponseAsync(cancellationToken).ConfigureAwait(false); @@ -466,12 +466,12 @@ public virtual async Task PairAsync(string host, int port, string code, } /// - public virtual async Task ConnectAsync(string host, int port = DefaultPort, CancellationToken cancellationToken = default) + public async Task ConnectAsync(string host, int port = DefaultPort, CancellationToken cancellationToken = default) { ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - string address = host.Contains(":") ? host : $"{host}:{port}"; + string address = host.Contains(':') ? host : $"{host}:{port}"; await socket.SendAdbRequestAsync($"host:connect:{address}", cancellationToken).ConfigureAwait(false); _ = await socket.ReadAdbResponseAsync(cancellationToken).ConfigureAwait(false); @@ -479,12 +479,12 @@ public virtual async Task ConnectAsync(string host, int port = DefaultPo } /// - public virtual async Task DisconnectAsync(string host, int port = DefaultPort, CancellationToken cancellationToken = default) + public async Task DisconnectAsync(string host, int port = DefaultPort, CancellationToken cancellationToken = default) { ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - string address = host.Contains(":") ? host : $"{host}:{port}"; + string address = host.Contains(':') ? host : $"{host}:{port}"; await socket.SendAdbRequestAsync($"host:disconnect:{address}", cancellationToken).ConfigureAwait(false); _ = await socket.ReadAdbResponseAsync(cancellationToken).ConfigureAwait(false); @@ -492,10 +492,10 @@ public virtual async Task DisconnectAsync(string host, int port = Defaul } /// - public virtual Task RootAsync(DeviceData device, CancellationToken cancellationToken = default) => RootAsync("root:", device, cancellationToken); + public Task RootAsync(DeviceData device, CancellationToken cancellationToken = default) => RootAsync("root:", device, cancellationToken); /// - public virtual Task UnrootAsync(DeviceData device, CancellationToken cancellationToken = default) => RootAsync("unroot:", device, cancellationToken); + public Task UnrootAsync(DeviceData device, CancellationToken cancellationToken = default) => RootAsync("unroot:", device, cancellationToken); /// /// Restarts the ADB daemon running on the device with or without root privileges. @@ -609,7 +609,7 @@ public virtual async Task InstallAsync(DeviceData device, Stream apk, Action - public virtual async Task InstallMultipleAsync(DeviceData device, Stream baseAPK, IEnumerable splitAPKs, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultipleAsync(DeviceData device, Stream baseAPK, IEnumerable splitAPKs, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -663,7 +663,7 @@ void OnSplitSyncProgressChanged(string? sender, double args) } /// - public virtual async Task InstallMultipleAsync(DeviceData device, IEnumerable splitAPKs, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultipleAsync(DeviceData device, IEnumerable splitAPKs, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -707,7 +707,7 @@ void OnSyncProgressChanged(string? sender, double args) } /// - public virtual async Task InstallCreateAsync(DeviceData device, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallCreateAsync(DeviceData device, CancellationToken cancellationToken = default, params string[] arguments) { EnsureDevice(device); @@ -742,7 +742,7 @@ public virtual async Task InstallCreateAsync(DeviceData device, Cancella } /// - public virtual async Task InstallCreateAsync(DeviceData device, string packageName, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallCreateAsync(DeviceData device, string packageName, CancellationToken cancellationToken = default, params string[] arguments) { EnsureDevice(device); ExceptionExtensions.ThrowIfNull(packageName); @@ -915,7 +915,7 @@ protected virtual async Task InstallWriteAsync(DeviceData device, Stream apk, st } /// - public virtual async Task InstallCommitAsync(DeviceData device, string session, CancellationToken cancellationToken = default) + public async Task InstallCommitAsync(DeviceData device, string session, CancellationToken cancellationToken = default) { using IAdbSocket socket = AdbSocketFactory(EndPoint); await socket.SetDeviceAsync(device, cancellationToken).ConfigureAwait(false); @@ -1001,7 +1001,7 @@ public virtual async Task InstallAsync(DeviceData device, IRandomAccessStream ap } /// - public virtual async Task InstallMultipleAsync(DeviceData device, IRandomAccessStream baseAPK, IEnumerable splitAPKs, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultipleAsync(DeviceData device, IRandomAccessStream baseAPK, IEnumerable splitAPKs, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -1055,7 +1055,7 @@ void OnSplitSyncProgressChanged(string? sender, double args) } /// - public virtual async Task InstallMultipleAsync(DeviceData device, IEnumerable splitAPKs, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultipleAsync(DeviceData device, IEnumerable splitAPKs, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -1233,7 +1233,7 @@ protected virtual async Task InstallWriteAsync(DeviceData device, IRandomAccessS #endif /// - public virtual async Task UninstallAsync(DeviceData device, string packageName, CancellationToken cancellationToken = default, params string[] arguments) + public async Task UninstallAsync(DeviceData device, string packageName, CancellationToken cancellationToken = default, params string[] arguments) { EnsureDevice(device); @@ -1264,7 +1264,7 @@ public virtual async Task UninstallAsync(DeviceData device, string packageName, } /// - public virtual async Task> GetFeatureSetAsync(DeviceData device, CancellationToken cancellationToken = default) + public async Task> GetFeatureSetAsync(DeviceData device, CancellationToken cancellationToken = default) { EnsureDevice(device); diff --git a/AdvancedSharpAdbClient/AdbClient.cs b/AdvancedSharpAdbClient/AdbClient.cs index 580f018..8844313 100644 --- a/AdvancedSharpAdbClient/AdbClient.cs +++ b/AdvancedSharpAdbClient/AdbClient.cs @@ -173,7 +173,7 @@ public static byte[] CreateAdbForwardRequest(string address, int port) } /// - public virtual int GetAdbVersion() + public int GetAdbVersion() { using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -185,7 +185,7 @@ public virtual int GetAdbVersion() } /// - public virtual void KillAdb() + public void KillAdb() { using IAdbSocket socket = AdbSocketFactory(EndPoint); socket.SendAdbRequest("host:kill"); @@ -195,7 +195,7 @@ public virtual void KillAdb() } /// - public virtual IEnumerable GetDevices() + public IEnumerable GetDevices() { using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -208,7 +208,7 @@ public virtual IEnumerable GetDevices() } /// - public virtual int CreateForward(DeviceData device, string local, string remote, bool allowRebind) + public int CreateForward(DeviceData device, string local, string remote, bool allowRebind) { EnsureDevice(device); @@ -224,7 +224,7 @@ public virtual int CreateForward(DeviceData device, string local, string remote, } /// - public virtual int CreateReverseForward(DeviceData device, string remote, string local, bool allowRebind) + public int CreateReverseForward(DeviceData device, string remote, string local, bool allowRebind) { EnsureDevice(device); @@ -242,7 +242,7 @@ public virtual int CreateReverseForward(DeviceData device, string remote, string } /// - public virtual void RemoveReverseForward(DeviceData device, string remote) + public void RemoveReverseForward(DeviceData device, string remote) { EnsureDevice(device); @@ -254,7 +254,7 @@ public virtual void RemoveReverseForward(DeviceData device, string remote) } /// - public virtual void RemoveAllReverseForwards(DeviceData device) + public void RemoveAllReverseForwards(DeviceData device) { EnsureDevice(device); @@ -266,7 +266,7 @@ public virtual void RemoveAllReverseForwards(DeviceData device) } /// - public virtual void RemoveForward(DeviceData device, int localPort) + public void RemoveForward(DeviceData device, int localPort) { EnsureDevice(device); @@ -276,7 +276,7 @@ public virtual void RemoveForward(DeviceData device, int localPort) } /// - public virtual void RemoveAllForwards(DeviceData device) + public void RemoveAllForwards(DeviceData device) { EnsureDevice(device); @@ -286,7 +286,7 @@ public virtual void RemoveAllForwards(DeviceData device) } /// - public virtual IEnumerable ListForward(DeviceData device) + public IEnumerable ListForward(DeviceData device) { EnsureDevice(device); @@ -300,7 +300,7 @@ public virtual IEnumerable ListForward(DeviceData device) } /// - public virtual IEnumerable ListReverseForward(DeviceData device) + public IEnumerable ListReverseForward(DeviceData device) { EnsureDevice(device); @@ -316,7 +316,7 @@ public virtual IEnumerable ListReverseForward(DeviceData device) } /// - public virtual void ExecuteServerCommand(string target, string command) + public void ExecuteServerCommand(string target, string command) { using IAdbSocket socket = AdbSocketFactory(EndPoint); ExecuteServerCommand(target, command, socket); @@ -337,7 +337,7 @@ public virtual void ExecuteServerCommand(string target, string command, IAdbSock } /// - public virtual void ExecuteRemoteCommand(string command, DeviceData device) + public void ExecuteRemoteCommand(string command, DeviceData device) { EnsureDevice(device); @@ -348,7 +348,7 @@ public virtual void ExecuteRemoteCommand(string command, DeviceData device) } /// - public virtual void ExecuteServerCommand(string target, string command, IShellOutputReceiver? receiver, Encoding encoding) + public void ExecuteServerCommand(string target, string command, IShellOutputReceiver? receiver, Encoding encoding) { ExceptionExtensions.ThrowIfNull(encoding); using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -395,7 +395,7 @@ public virtual void ExecuteServerCommand(string target, string command, IAdbSock } /// - public virtual void ExecuteRemoteCommand(string command, DeviceData device, IShellOutputReceiver? receiver, Encoding encoding) + public void ExecuteRemoteCommand(string command, DeviceData device, IShellOutputReceiver? receiver, Encoding encoding) { EnsureDevice(device); @@ -406,7 +406,7 @@ public virtual void ExecuteRemoteCommand(string command, DeviceData device, IShe } /// - public virtual IEnumerable ExecuteServerCommand(string target, string command, Encoding encoding) + public IEnumerable ExecuteServerCommand(string target, string command, Encoding encoding) { ExceptionExtensions.ThrowIfNull(encoding); using IAdbSocket socket = AdbSocketFactory(EndPoint); @@ -453,7 +453,7 @@ public virtual IEnumerable ExecuteServerCommand(string target, string co } /// - public virtual IEnumerable ExecuteRemoteCommand(string command, DeviceData device, Encoding encoding) + public IEnumerable ExecuteRemoteCommand(string command, DeviceData device, Encoding encoding) { EnsureDevice(device); @@ -467,7 +467,7 @@ public virtual IEnumerable ExecuteRemoteCommand(string command, DeviceDa } /// - public virtual IEnumerable RunLogService(DeviceData device, params LogId[] logNames) + public IEnumerable RunLogService(DeviceData device, params LogId[] logNames) { EnsureDevice(device); @@ -513,7 +513,7 @@ public virtual IEnumerable RunLogService(DeviceData device, params Log } /// - public virtual void RunLogService(DeviceData device, Action messageSink, in bool isCancelled = false, params LogId[] logNames) + public void RunLogService(DeviceData device, Action messageSink, in bool isCancelled = false, params LogId[] logNames) { EnsureDevice(device); ExceptionExtensions.ThrowIfNull(messageSink); @@ -560,14 +560,14 @@ public virtual void RunLogService(DeviceData device, Action messageSin } /// - public virtual Framebuffer CreateFramebuffer(DeviceData device) + public Framebuffer CreateFramebuffer(DeviceData device) { EnsureDevice(device); return new Framebuffer(device, this, AdbSocketFactory); } /// - public virtual Framebuffer GetFrameBuffer(DeviceData device) + public Framebuffer GetFrameBuffer(DeviceData device) { EnsureDevice(device); @@ -579,7 +579,7 @@ public virtual Framebuffer GetFrameBuffer(DeviceData device) } /// - public virtual void Reboot(string into, DeviceData device) + public void Reboot(string into, DeviceData device) { EnsureDevice(device); @@ -591,25 +591,25 @@ public virtual void Reboot(string into, DeviceData device) } /// - public virtual string Pair(string host, int port, string code) + public string Pair(string host, int port, string code) { ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - string address = host.Contains(":") ? host : $"{host}:{port}"; - socket.SendAdbRequest($"host:pair:{address}:{port}"); + string address = host.Contains(':') ? host : $"{host}:{port}"; + socket.SendAdbRequest($"host:pair:{code}:{address}"); _ = socket.ReadAdbResponse(); return socket.ReadString(); } /// - public virtual string Connect(string host, int port = DefaultPort) + public string Connect(string host, int port = DefaultPort) { ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - string address = host.Contains(":") ? host : $"{host}:{port}"; + string address = host.Contains(':') ? host : $"{host}:{port}"; socket.SendAdbRequest($"host:connect:{address}"); _ = socket.ReadAdbResponse(); @@ -617,12 +617,12 @@ public virtual string Connect(string host, int port = DefaultPort) } /// - public virtual string Disconnect(string host, int port = DefaultPort) + public string Disconnect(string host, int port = DefaultPort) { ExceptionExtensions.ThrowIfNull(host); using IAdbSocket socket = AdbSocketFactory(EndPoint); - string address = host.Contains(":") ? host : $"{host}:{port}"; + string address = host.Contains(':') ? host : $"{host}:{port}"; socket.SendAdbRequest($"host:disconnect:{address}"); _ = socket.ReadAdbResponse(); @@ -630,17 +630,17 @@ public virtual string Disconnect(string host, int port = DefaultPort) } /// - public virtual void Root(DeviceData device) => Root("root:", device); + public void Root(DeviceData device) => Root("root:", device); /// - public virtual void Unroot(DeviceData device) => Root("unroot:", device); + public void Unroot(DeviceData device) => Root("unroot:", device); /// /// Restarts the ADB daemon running on the device with or without root privileges. /// /// The command of root or unroot. /// The device on which to restart ADB with root privileges. - protected virtual void Root(string request, DeviceData device) + protected void Root(string request, DeviceData device) { EnsureDevice(device); @@ -748,7 +748,7 @@ public virtual void Install(DeviceData device, Stream apk, Action - public virtual void InstallMultiple(DeviceData device, Stream baseAPK, IEnumerable splitAPKs, Action? callback = null, params string[] arguments) + public void InstallMultiple(DeviceData device, Stream baseAPK, IEnumerable splitAPKs, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -805,7 +805,7 @@ void OnSplitSyncProgressChanged(string? sender, double args) } /// - public virtual void InstallMultiple(DeviceData device, IEnumerable splitAPKs, string packageName, Action? callback = null, params string[] arguments) + public void InstallMultiple(DeviceData device, IEnumerable splitAPKs, string packageName, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -852,7 +852,7 @@ void OnSyncProgressChanged(string? sender, double args) } /// - public virtual string InstallCreate(DeviceData device, params string[] arguments) + public string InstallCreate(DeviceData device, params string[] arguments) { EnsureDevice(device); @@ -886,7 +886,7 @@ public virtual string InstallCreate(DeviceData device, params string[] arguments } /// - public virtual string InstallCreate(DeviceData device, string packageName, params string[] arguments) + public string InstallCreate(DeviceData device, string packageName, params string[] arguments) { EnsureDevice(device); ExceptionExtensions.ThrowIfNull(packageName); @@ -1055,7 +1055,7 @@ protected virtual void InstallWrite(DeviceData device, Stream apk, string apkNam } /// - public virtual void InstallCommit(DeviceData device, string session) + public void InstallCommit(DeviceData device, string session) { EnsureDevice(device); @@ -1074,7 +1074,7 @@ public virtual void InstallCommit(DeviceData device, string session) } /// - public virtual void Uninstall(DeviceData device, string packageName, params string[] arguments) + public void Uninstall(DeviceData device, string packageName, params string[] arguments) { EnsureDevice(device); @@ -1105,7 +1105,7 @@ public virtual void Uninstall(DeviceData device, string packageName, params stri } /// - public virtual IEnumerable GetFeatureSet(DeviceData device) + public IEnumerable GetFeatureSet(DeviceData device) { EnsureDevice(device); diff --git a/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs b/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs index e6f26c8..7fd5e3a 100644 --- a/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs +++ b/AdvancedSharpAdbClient/AdbCommandLineClient.Async.cs @@ -16,7 +16,7 @@ namespace AdvancedSharpAdbClient public partial class AdbCommandLineClient { /// - public virtual async Task GetVersionAsync(CancellationToken cancellationToken = default) + public async Task GetVersionAsync(CancellationToken cancellationToken = default) { // Run the adb.exe version command and capture the output. List standardOutput = []; @@ -55,40 +55,16 @@ public virtual async Task> ExecuteAdbCommandAsync(string command, C } /// - public virtual async Task StartServerAsync(CancellationToken cancellationToken = default) + public async Task StartServerAsync(CancellationToken cancellationToken = default) { int status = await RunAdbProcessInnerAsync("start-server", null, null, cancellationToken).ConfigureAwait(false); if (status == 0) { return; } -#if HAS_PROCESS && !WINDOWS_UWP - try - { - // Starting the adb server failed for whatever reason. This can happen if adb.exe - // is running but is not accepting requests. In that case, try to kill it & start again. - // It kills all processes named "adb", so let's hope nobody else named their process that way. - foreach (Process adbProcess in Process.GetProcessesByName("adb")) - { - try - { - adbProcess.Kill(); - } - catch (Win32Exception) - { - // The associated process could not be terminated - // or - // The process is terminating. - } - catch (InvalidOperationException) - { - // The process has already exited. - // There is no process associated with this Process object. - } - } - } - catch (NotSupportedException) - { - // This platform does not support getting a list of processes. - } -#endif + + // Starting the adb server failed for whatever reason. This can happen if adb.exe + // is running but is not accepting requests. In that case, try to kill it & start again. + // It kills all processes named "adb", so let's hope nobody else named their process that way. + KillProcess("adb"); + // Try again. This time, we don't call "Inner", and an exception will be thrown if the start operation fails // again. We'll let that exception bubble up the stack. await RunAdbProcessAsync("start-server", null, null, cancellationToken).ConfigureAwait(false); @@ -116,7 +92,7 @@ public virtual Task CheckAdbFileExistsAsync(string adbPath, CancellationTo /// Use this command only for adb commands that return immediately, such as /// adb version. This operation times out after 5 seconds. /// The process exited with an exit code other than 0. - protected virtual async Task RunAdbProcessAsync(string command, ICollection? errorOutput, ICollection? standardOutput, CancellationToken cancellationToken = default) + protected async Task RunAdbProcessAsync(string command, ICollection? errorOutput, ICollection? standardOutput, CancellationToken cancellationToken = default) { int status = await RunAdbProcessInnerAsync(command, errorOutput, standardOutput, cancellationToken).ConfigureAwait(false); if (status != 0) { throw new AdbException($"The adb process returned error code {status} when running command {command}"); } @@ -135,7 +111,7 @@ protected virtual async Task RunAdbProcessAsync(string command, ICollectionA which returns the return code of the adb process. /// Use this command only for adb commands that return immediately, such as /// adb version. This operation times out after 5 seconds. - protected virtual async Task RunAdbProcessInnerAsync(string command, ICollection? errorOutput, ICollection? standardOutput, CancellationToken cancellationToken = default) + protected async Task RunAdbProcessInnerAsync(string command, ICollection? errorOutput, ICollection? standardOutput, CancellationToken cancellationToken = default) { ExceptionExtensions.ThrowIfNull(command); return await RunProcessAsync(AdbPath, command, errorOutput, standardOutput, cancellationToken).ConfigureAwait(false); diff --git a/AdvancedSharpAdbClient/AdbCommandLineClient.cs b/AdvancedSharpAdbClient/AdbCommandLineClient.cs index c5ba748..d158716 100644 --- a/AdvancedSharpAdbClient/AdbCommandLineClient.cs +++ b/AdvancedSharpAdbClient/AdbCommandLineClient.cs @@ -60,7 +60,7 @@ public AdbCommandLineClient(string adbPath, bool isForce = false, ILogger - public virtual AdbCommandLineStatus GetVersion() + public AdbCommandLineStatus GetVersion() { // Run the adb.exe version command and capture the output. List standardOutput = []; @@ -84,40 +84,16 @@ public virtual AdbCommandLineStatus GetVersion() } /// - public virtual void StartServer() + public void StartServer() { int status = RunAdbProcessInner("start-server", null, null); if (status == 0) { return; } -#if HAS_PROCESS && !WINDOWS_UWP - try - { - // Starting the adb server failed for whatever reason. This can happen if adb.exe - // is running but is not accepting requests. In that case, try to kill it & start again. - // It kills all processes named "adb", so let's hope nobody else named their process that way. - foreach (Process adbProcess in Process.GetProcessesByName("adb")) - { - try - { - adbProcess.Kill(); - } - catch (Win32Exception) - { - // The associated process could not be terminated - // or - // The process is terminating. - } - catch (InvalidOperationException) - { - // The process has already exited. - // There is no process associated with this Process object. - } - } - } - catch (NotSupportedException) - { - // This platform does not support getting a list of processes. - } -#endif + + // Starting the adb server failed for whatever reason. This can happen if adb.exe + // is running but is not accepting requests. In that case, try to kill it & start again. + // It kills all processes named "adb", so let's hope nobody else named their process that way. + KillProcess("adb"); + // Try again. This time, we don't call "Inner", and an exception will be thrown if the start operation fails // again. We'll let that exception bubble up the stack. RunAdbProcess("start-server", null, null); @@ -189,7 +165,7 @@ protected virtual void EnsureIsValidAdbFile(string adbPath) /// Use this command only for adb commands that return immediately, such as /// adb version. This operation times out after 5 seconds. /// The process exited with an exit code other than 0. - protected virtual void RunAdbProcess(string command, ICollection? errorOutput, ICollection? standardOutput) + protected void RunAdbProcess(string command, ICollection? errorOutput, ICollection? standardOutput) { int status = RunAdbProcessInner(command, errorOutput, standardOutput); if (status != 0) { throw new AdbException($"The adb process returned error code {status} when running command {command}"); } @@ -207,12 +183,47 @@ protected virtual void RunAdbProcess(string command, ICollection? errorO /// The return code of the adb process. /// Use this command only for adb commands that return immediately, such as /// adb version. This operation times out after 5 seconds. - protected virtual int RunAdbProcessInner(string command, ICollection? errorOutput, ICollection? standardOutput) + protected int RunAdbProcessInner(string command, ICollection? errorOutput, ICollection? standardOutput) { ExceptionExtensions.ThrowIfNull(command); return RunProcess(AdbPath, command, errorOutput, standardOutput); } + /// + /// Kills all processes with the specified name. + /// + /// The name of the process to kill. + protected virtual void KillProcess(string processName) + { +#if HAS_PROCESS && !WINDOWS_UWP + try + { + foreach (Process adbProcess in Process.GetProcessesByName(processName)) + { + try + { + adbProcess.Kill(); + } + catch (Win32Exception) + { + // The associated process could not be terminated + // or + // The process is terminating. + } + catch (InvalidOperationException) + { + // The process has already exited. + // There is no process associated with this Process object. + } + } + } + catch (NotSupportedException) + { + // This platform does not support getting a list of processes. + } +#endif + } + /// /// Runs process, invoking a specific command, and reads the standard output and standard error output. /// diff --git a/AdvancedSharpAdbClient/AdbServer.Async.cs b/AdvancedSharpAdbClient/AdbServer.Async.cs index 9e9181e..6282284 100644 --- a/AdvancedSharpAdbClient/AdbServer.Async.cs +++ b/AdvancedSharpAdbClient/AdbServer.Async.cs @@ -13,7 +13,7 @@ namespace AdvancedSharpAdbClient public partial class AdbServer { /// - public virtual async Task StartServerAsync(string adbPath, bool restartServerIfNewer = false, CancellationToken cancellationToken = default) + public async Task StartServerAsync(string adbPath, bool restartServerIfNewer = false, CancellationToken cancellationToken = default) { if (IsStarting) { return StartServerResult.Starting; } try @@ -70,11 +70,11 @@ public Task RestartServerAsync(CancellationToken cancellation StartServerAsync(CachedAdbPath!, true, cancellationToken); /// - public virtual Task RestartServerAsync(string adbPath, CancellationToken cancellationToken = default) => + public Task RestartServerAsync(string adbPath, CancellationToken cancellationToken = default) => StringExtensions.IsNullOrWhiteSpace(adbPath) ? RestartServerAsync(cancellationToken) : StartServerAsync(adbPath, true, cancellationToken); /// - public virtual async Task StopServerAsync(CancellationToken cancellationToken = default) + public async Task StopServerAsync(CancellationToken cancellationToken = default) { using IAdbSocket socket = AdbSocketFactory(EndPoint); await socket.SendAdbRequestAsync("host:kill", cancellationToken).ConfigureAwait(false); @@ -84,7 +84,7 @@ public virtual async Task StopServerAsync(CancellationToken cancellationToken = } /// - public virtual async Task GetStatusAsync(CancellationToken cancellationToken = default) + public async Task GetStatusAsync(CancellationToken cancellationToken = default) { // Try to connect to a running instance of the adb server try diff --git a/AdvancedSharpAdbClient/AdbServer.cs b/AdvancedSharpAdbClient/AdbServer.cs index 823a4fd..4e12701 100644 --- a/AdvancedSharpAdbClient/AdbServer.cs +++ b/AdvancedSharpAdbClient/AdbServer.cs @@ -165,7 +165,7 @@ public AdbServer(Func adbSocketFactory, Func - public virtual StartServerResult StartServer(string adbPath, bool restartServerIfNewer = false) + public StartServerResult StartServer(string adbPath, bool restartServerIfNewer = false) { if (IsStarting) { return StartServerResult.Starting; } try @@ -218,14 +218,14 @@ public virtual StartServerResult StartServer(string adbPath, bool restartServerI } /// - public virtual StartServerResult RestartServer() => StartServer(CachedAdbPath!, true); + public StartServerResult RestartServer() => StartServer(CachedAdbPath!, true); /// - public virtual StartServerResult RestartServer(string adbPath) => + public StartServerResult RestartServer(string adbPath) => StringExtensions.IsNullOrWhiteSpace(adbPath) ? RestartServer() : StartServer(adbPath, true); /// - public virtual void StopServer() + public void StopServer() { using IAdbSocket socket = AdbSocketFactory(EndPoint); socket.SendAdbRequest("host:kill"); @@ -235,7 +235,7 @@ public virtual void StopServer() } /// - public virtual AdbServerStatus GetStatus() + public AdbServerStatus GetStatus() { // Try to connect to a running instance of the adb server try diff --git a/AdvancedSharpAdbClient/AdbSocket.Async.cs b/AdvancedSharpAdbClient/AdbSocket.Async.cs index 15f31c2..90cc8a8 100644 --- a/AdvancedSharpAdbClient/AdbSocket.Async.cs +++ b/AdvancedSharpAdbClient/AdbSocket.Async.cs @@ -22,7 +22,7 @@ public partial class AdbSocket public Task ReconnectAsync(CancellationToken cancellationToken = default) => ReconnectAsync(false, cancellationToken); /// - public virtual Task ReconnectAsync(bool isForce, CancellationToken cancellationToken = default) => Socket.ReconnectAsync(isForce, cancellationToken); + public Task ReconnectAsync(bool isForce, CancellationToken cancellationToken = default) => Socket.ReconnectAsync(isForce, cancellationToken); /// public virtual async Task SendAsync(byte[] data, CancellationToken cancellationToken = default) @@ -83,7 +83,7 @@ public Task SendSyncRequestAsync(SyncCommand command, string path, int permissio SendSyncRequestAsync(command, $"{path},{permissions}", cancellationToken); /// - public virtual async Task SendSyncRequestAsync(SyncCommand command, string path, CancellationToken cancellationToken = default) + public async Task SendSyncRequestAsync(SyncCommand command, string path, CancellationToken cancellationToken = default) { ExceptionExtensions.ThrowIfNull(path); byte[] pathBytes = AdbClient.Encoding.GetBytes(path); @@ -92,7 +92,7 @@ public virtual async Task SendSyncRequestAsync(SyncCommand command, string path, } /// - public virtual async Task SendSyncRequestAsync(SyncCommand command, int length, CancellationToken cancellationToken = default) + public async Task SendSyncRequestAsync(SyncCommand command, int length, CancellationToken cancellationToken = default) { // The message structure is: // First four bytes: command @@ -113,7 +113,7 @@ public virtual async Task SendSyncRequestAsync(SyncCommand command, int length, } /// - public virtual async Task SendAdbRequestAsync(string request, CancellationToken cancellationToken = default) + public async Task SendAdbRequestAsync(string request, CancellationToken cancellationToken = default) { byte[] data = AdbClient.FormAdbRequest(request); if (!await WriteAsync(data, cancellationToken).ConfigureAwait(false)) @@ -234,7 +234,7 @@ public virtual async Task ReadSyncStringAsync(CancellationToken cancella } /// - public virtual async Task ReadSyncResponseAsync(CancellationToken cancellationToken = default) + public async Task ReadSyncResponseAsync(CancellationToken cancellationToken = default) { byte[] data = new byte[4]; _ = await ReadAsync(data, cancellationToken).ConfigureAwait(false); @@ -242,7 +242,7 @@ public virtual async Task ReadSyncResponseAsync(CancellationToken c } /// - public virtual async Task ReadAdbResponseAsync(CancellationToken cancellationToken = default) + public async Task ReadAdbResponseAsync(CancellationToken cancellationToken = default) { AdbResponse response = await ReadAdbResponseInnerAsync(cancellationToken).ConfigureAwait(false); @@ -256,7 +256,7 @@ public virtual async Task ReadAdbResponseAsync(CancellationToken ca } /// - public virtual async Task SetDeviceAsync(DeviceData device, CancellationToken cancellationToken = default) + public async Task SetDeviceAsync(DeviceData device, CancellationToken cancellationToken = default) { // if the device is not null, then we first tell adb we're looking to talk // to a specific device diff --git a/AdvancedSharpAdbClient/AdbSocket.cs b/AdvancedSharpAdbClient/AdbSocket.cs index 439827b..363e693 100644 --- a/AdvancedSharpAdbClient/AdbSocket.cs +++ b/AdvancedSharpAdbClient/AdbSocket.cs @@ -86,7 +86,7 @@ public AdbSocket(string host, int port, ILogger? logger = null) public bool Connected => Socket.Connected; /// - public virtual void Reconnect(bool isForce = false) => Socket.Reconnect(isForce); + public void Reconnect(bool isForce = false) => Socket.Reconnect(isForce); /// public virtual void Send(byte[] data) @@ -147,7 +147,7 @@ public void SendSyncRequest(SyncCommand command, string path, int permissions) = SendSyncRequest(command, $"{path},{permissions}"); /// - public virtual void SendSyncRequest(SyncCommand command, string path) + public void SendSyncRequest(SyncCommand command, string path) { ExceptionExtensions.ThrowIfNull(path); byte[] pathBytes = AdbClient.Encoding.GetBytes(path); @@ -156,7 +156,7 @@ public virtual void SendSyncRequest(SyncCommand command, string path) } /// - public virtual void SendSyncRequest(SyncCommand command, int length) + public void SendSyncRequest(SyncCommand command, int length) { // The message structure is: // First four bytes: command @@ -177,7 +177,7 @@ public virtual void SendSyncRequest(SyncCommand command, int length) } /// - public virtual void SendAdbRequest(string request) + public void SendAdbRequest(string request) { byte[] data = AdbClient.FormAdbRequest(request); if (!Write(data)) @@ -296,7 +296,7 @@ public virtual string ReadSyncString() } /// - public virtual SyncCommand ReadSyncResponse() + public SyncCommand ReadSyncResponse() { byte[] data = new byte[4]; _ = Read(data); @@ -304,7 +304,7 @@ public virtual SyncCommand ReadSyncResponse() } /// - public virtual AdbResponse ReadAdbResponse() + public AdbResponse ReadAdbResponse() { AdbResponse response = ReadAdbResponseInner(); @@ -480,7 +480,7 @@ protected virtual AdbResponse ReadAdbResponseInner() /// /// A array that represents the ADB reply. /// A that represents the ADB reply. - protected virtual string ReplyToString(byte[] reply) + protected string ReplyToString(byte[] reply) { string result; try @@ -501,7 +501,7 @@ protected virtual string ReplyToString(byte[] reply) /// /// A array that represents the ADB reply. /// A that represents the ADB reply. - protected virtual string ReplyToString(ReadOnlySpan reply) + protected string ReplyToString(ReadOnlySpan reply) { string result; try @@ -536,7 +536,7 @@ public void Dispose() } /// - public virtual void Close() => Socket.Dispose(); + public void Close() => Socket.Dispose(); /// /// Creates a new instance based on the specified . diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs index 52bda8b..4649efe 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs @@ -21,7 +21,7 @@ public partial class DeviceClient /// A which can be used to cancel the asynchronous operation. /// A which returns a containing current hierarchy. /// Failed if start with ERROR or java.lang.Exception. - public virtual async Task DumpScreenStringAsync(CancellationToken cancellationToken = default) + public async Task DumpScreenStringAsync(CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, "uiautomator dump /dev/tty", receiver, cancellationToken).ConfigureAwait(false); @@ -46,7 +46,7 @@ public virtual async Task DumpScreenStringAsync(CancellationToken cancel /// /// A which can be used to cancel the asynchronous operation. /// A which returns a containing current hierarchy. - public virtual async Task DumpScreenAsync(CancellationToken cancellationToken = default) + public async Task DumpScreenAsync(CancellationToken cancellationToken = default) { string xmlString = await DumpScreenStringAsync(cancellationToken).ConfigureAwait(false); XmlDocument doc = new(); @@ -64,7 +64,7 @@ public virtual async Task DumpScreenStringAsync(CancellationToken cancel /// /// A which can be used to cancel the asynchronous operation. /// A which returns a containing current hierarchy. - public virtual async Task DumpScreenWinRTAsync(CancellationToken cancellationToken = default) + public async Task DumpScreenWinRTAsync(CancellationToken cancellationToken = default) { string xmlString = await DumpScreenStringAsync(cancellationToken).ConfigureAwait(false); Windows.Data.Xml.Dom.XmlDocument doc = new(); @@ -83,7 +83,7 @@ public virtual async Task DumpScreenStringAsync(CancellationToken cancel /// The to click. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual async Task ClickAsync(Point cords, CancellationToken cancellationToken = default) + public async Task ClickAsync(Point cords, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input tap {cords.X} {cords.Y}", receiver, cancellationToken).ConfigureAwait(false); @@ -107,7 +107,7 @@ public virtual async Task ClickAsync(Point cords, CancellationToken cancellation /// The Y co-ordinate to click. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual async Task ClickAsync(int x, int y, CancellationToken cancellationToken = default) + public async Task ClickAsync(int x, int y, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input tap {x} {y}", receiver, cancellationToken).ConfigureAwait(false); @@ -132,7 +132,7 @@ public virtual async Task ClickAsync(int x, int y, CancellationToken cancellatio /// The time spent in swiping. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual async Task SwipeAsync(Element first, Element second, long speed, CancellationToken cancellationToken = default) + public async Task SwipeAsync(Element first, Element second, long speed, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input swipe {first.Center.X} {first.Center.Y} {second.Center.X} {second.Center.Y} {speed}", receiver, cancellationToken).ConfigureAwait(false); @@ -157,7 +157,7 @@ public virtual async Task SwipeAsync(Element first, Element second, long speed, /// The time spent in swiping. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual async Task SwipeAsync(Point first, Point second, long speed, CancellationToken cancellationToken = default) + public async Task SwipeAsync(Point first, Point second, long speed, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input swipe {first.X} {first.Y} {second.X} {second.Y} {speed}", receiver, cancellationToken).ConfigureAwait(false); @@ -184,7 +184,7 @@ public virtual async Task SwipeAsync(Point first, Point second, long speed, Canc /// The time spent in swiping. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual async Task SwipeAsync(int x1, int y1, int x2, int y2, long speed, CancellationToken cancellationToken = default) + public async Task SwipeAsync(int x1, int y1, int x2, int y2, long speed, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input swipe {x1} {y1} {x2} {y2} {speed}", receiver, cancellationToken).ConfigureAwait(false); @@ -207,7 +207,7 @@ public virtual async Task SwipeAsync(int x1, int y1, int x2, int y2, long speed, /// The package name of the app to check. /// A which can be used to cancel the asynchronous operation. /// A which returns the result. if the app is running in foreground; otherwise, . - public virtual async Task IsAppRunningAsync(string packageName, CancellationToken cancellationToken = default) + public async Task IsAppRunningAsync(string packageName, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { TrimLines = true, ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"pidof {packageName}", receiver, cancellationToken).ConfigureAwait(false); @@ -223,7 +223,7 @@ public virtual async Task IsAppRunningAsync(string packageName, Cancellati /// The package name of the app to check. /// A which can be used to cancel the asynchronous operation. /// A which returns the result. if the app is running in background; otherwise, . - public virtual async Task IsAppInForegroundAsync(string packageName, CancellationToken cancellationToken = default) + public async Task IsAppInForegroundAsync(string packageName, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { TrimLines = true, ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"dumpsys activity activities | grep mResumedActivity", receiver, cancellationToken).ConfigureAwait(false); @@ -238,7 +238,7 @@ public virtual async Task IsAppInForegroundAsync(string packageName, Cance /// The package name of the app to check. /// A which can be used to cancel the asynchronous operation. /// A which returns the of the app. Foreground, stopped or running in background. - public virtual async Task GetAppStatusAsync(string packageName, CancellationToken cancellationToken = default) + public async Task GetAppStatusAsync(string packageName, CancellationToken cancellationToken = default) { // Check if the app is in foreground bool currentApp = await IsAppInForegroundAsync(packageName, cancellationToken).ConfigureAwait(false); @@ -259,7 +259,7 @@ public virtual async Task GetAppStatusAsync(string packageName, Cance /// A which can be used to cancel the asynchronous operation. /// Only check once if . Or it will continue check until is . /// A which returns the of . - public virtual async Task FindElementAsync(string xpath = "hierarchy/node", CancellationToken cancellationToken = default) + public async Task FindElementAsync(string xpath = "hierarchy/node", CancellationToken cancellationToken = default) { try { @@ -308,7 +308,7 @@ public virtual async Task GetAppStatusAsync(string packageName, Cance /// A which can be used to cancel the asynchronous operation. /// Only check once if . Or it will continue check until is . /// A which returns the of has got. - public virtual async Task> FindElementsAsync(string xpath = "hierarchy/node", CancellationToken cancellationToken = default) + public async Task> FindElementsAsync(string xpath = "hierarchy/node", CancellationToken cancellationToken = default) { try { @@ -365,7 +365,7 @@ static IEnumerable FindElements(IAdbClient client, DeviceData device, X /// A which can be used to cancel the asynchronous operation. /// Only check once if . Or it will continue check until is . /// The of has got. - public virtual async IAsyncEnumerable FindAsyncElements(string xpath = "hierarchy/node", [EnumeratorCancellation] CancellationToken cancellationToken = default) + public async IAsyncEnumerable FindAsyncElements(string xpath = "hierarchy/node", [EnumeratorCancellation] CancellationToken cancellationToken = default) { while (!cancellationToken.IsCancellationRequested) { @@ -418,7 +418,7 @@ public virtual async IAsyncEnumerable FindAsyncElements(string xpath = /// The key event to send. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual async Task SendKeyEventAsync(string key, CancellationToken cancellationToken = default) + public async Task SendKeyEventAsync(string key, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input keyevent {key}", receiver, cancellationToken).ConfigureAwait(false); @@ -441,7 +441,7 @@ public virtual async Task SendKeyEventAsync(string key, CancellationToken cancel /// The text to send. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual async Task SendTextAsync(string text, CancellationToken cancellationToken = default) + public async Task SendTextAsync(string text, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input text {text}", receiver, cancellationToken).ConfigureAwait(false); @@ -464,7 +464,7 @@ public virtual async Task SendTextAsync(string text, CancellationToken cancellat /// The package name of the application to start. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual Task StartAppAsync(string packageName, CancellationToken cancellationToken = default) => AdbClient.ExecuteShellCommandAsync(Device, $"monkey -p {packageName} 1", cancellationToken); + public Task StartAppAsync(string packageName, CancellationToken cancellationToken = default) => AdbClient.ExecuteShellCommandAsync(Device, $"monkey -p {packageName} 1", cancellationToken); /// /// Stop an Android application on device asynchronously. @@ -472,7 +472,7 @@ public virtual async Task SendTextAsync(string text, CancellationToken cancellat /// The package name of the application to stop. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual Task StopAppAsync(string packageName, CancellationToken cancellationToken = default) => AdbClient.ExecuteShellCommandAsync(Device, $"am force-stop {packageName}", cancellationToken); + public Task StopAppAsync(string packageName, CancellationToken cancellationToken = default) => AdbClient.ExecuteShellCommandAsync(Device, $"am force-stop {packageName}", cancellationToken); } } #endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs index 774da5f..a9327dd 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs @@ -49,7 +49,7 @@ public DeviceClient(IAdbClient client, DeviceData device) /// /// A containing current hierarchy. /// Failed if start with ERROR or java.lang.Exception. - public virtual string DumpScreenString() + public string DumpScreenString() { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, "uiautomator dump /dev/tty", receiver); @@ -73,7 +73,7 @@ public virtual string DumpScreenString() /// Gets the current device screen snapshot. /// /// A containing current hierarchy. - public virtual XmlDocument? DumpScreen() + public XmlDocument? DumpScreen() { XmlDocument doc = new(); string xmlString = DumpScreenString(); @@ -90,7 +90,7 @@ public virtual string DumpScreenString() /// Gets the current device screen snapshot. /// /// A containing current hierarchy. - public virtual Windows.Data.Xml.Dom.XmlDocument? DumpScreenWinRT() + public Windows.Data.Xml.Dom.XmlDocument? DumpScreenWinRT() { Windows.Data.Xml.Dom.XmlDocument doc = new(); string xmlString = DumpScreenString(); @@ -107,7 +107,7 @@ public virtual string DumpScreenString() /// Clicks on the specified coordinates. /// /// The to click. - public virtual void Click(Point cords) + public void Click(Point cords) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input tap {cords.X} {cords.Y}", receiver); @@ -129,7 +129,7 @@ public virtual void Click(Point cords) /// /// The X co-ordinate to click. /// The Y co-ordinate to click. - public virtual void Click(int x, int y) + public void Click(int x, int y) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input tap {x} {y}", receiver); @@ -152,7 +152,7 @@ public virtual void Click(int x, int y) /// The start element. /// The end element. /// The time spent in swiping. - public virtual void Swipe(Element first, Element second, long speed) + public void Swipe(Element first, Element second, long speed) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input swipe {first.Center.X} {first.Center.Y} {second.Center.X} {second.Center.Y} {speed}", receiver); @@ -175,7 +175,7 @@ public virtual void Swipe(Element first, Element second, long speed) /// The start . /// The end . /// The time spent in swiping. - public virtual void Swipe(Point first, Point second, long speed) + public void Swipe(Point first, Point second, long speed) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input swipe {first.X} {first.Y} {second.X} {second.Y} {speed}", receiver); @@ -200,7 +200,7 @@ public virtual void Swipe(Point first, Point second, long speed) /// The end X co-ordinate. /// The end Y co-ordinate. /// The time spent in swiping. - public virtual void Swipe(int x1, int y1, int x2, int y2, long speed) + public void Swipe(int x1, int y1, int x2, int y2, long speed) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input swipe {x1} {y1} {x2} {y2} {speed}", receiver); @@ -222,7 +222,7 @@ public virtual void Swipe(int x1, int y1, int x2, int y2, long speed) /// /// The package name of the app to check. /// if the app is running in foreground; otherwise, . - public virtual bool IsAppRunning(string packageName) + public bool IsAppRunning(string packageName) { ConsoleOutputReceiver receiver = new() { TrimLines = true, ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"pidof {packageName}", receiver); @@ -237,7 +237,7 @@ public virtual bool IsAppRunning(string packageName) /// /// The package name of the app to check. /// if the app is running in background; otherwise, . - public virtual bool IsAppInForeground(string packageName) + public bool IsAppInForeground(string packageName) { ConsoleOutputReceiver receiver = new() { TrimLines = true, ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"dumpsys activity activities | grep mResumedActivity", receiver); @@ -251,7 +251,7 @@ public virtual bool IsAppInForeground(string packageName) /// /// The package name of the app to check. /// The of the app. Foreground, stopped or running in background. - public virtual AppStatus GetAppStatus(string packageName) + public AppStatus GetAppStatus(string packageName) { // Check if the app is in foreground bool currentApp = IsAppInForeground(packageName); @@ -272,7 +272,7 @@ public virtual AppStatus GetAppStatus(string packageName) /// The timeout for waiting the element. /// Only check once if or . /// The of . - public virtual Element? FindElement(string xpath = "hierarchy/node", TimeSpan timeout = default) + public Element? FindElement(string xpath = "hierarchy/node", TimeSpan timeout = default) { Stopwatch stopwatch = new(); stopwatch.Start(); @@ -311,7 +311,7 @@ public virtual AppStatus GetAppStatus(string packageName) /// The timeout for waiting the elements. /// Only check once if or . /// The of has got. - public virtual IEnumerable FindElements(string xpath = "hierarchy/node", TimeSpan timeout = default) + public IEnumerable FindElements(string xpath = "hierarchy/node", TimeSpan timeout = default) { Stopwatch stopwatch = new(); stopwatch.Start(); @@ -354,7 +354,7 @@ public virtual IEnumerable FindElements(string xpath = "hierarchy/node" /// Send key event to specific. You can see key events here https://developer.android.com/reference/android/view/KeyEvent. /// /// The key event to send. - public virtual void SendKeyEvent(string key) + public void SendKeyEvent(string key) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input keyevent {key}", receiver); @@ -375,7 +375,7 @@ public virtual void SendKeyEvent(string key) /// Send text to device. Doesn't support Russian. /// /// The text to send. - public virtual void SendText(string text) + public void SendText(string text) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input text {text}", receiver); @@ -396,20 +396,20 @@ public virtual void SendText(string text) /// Start an Android application on device. /// /// The package name of the application to start. - public virtual void StartApp(string packageName) => AdbClient.ExecuteShellCommand(Device, $"monkey -p {packageName} 1"); + public void StartApp(string packageName) => AdbClient.ExecuteShellCommand(Device, $"monkey -p {packageName} 1"); /// /// Stop an Android application on device. /// /// The package name of the application to stop. - public virtual void StopApp(string packageName) => AdbClient.ExecuteShellCommand(Device, $"am force-stop {packageName}"); + public void StopApp(string packageName) => AdbClient.ExecuteShellCommand(Device, $"am force-stop {packageName}"); /// /// Deconstruct the class. /// /// The to use to communicate with the Android Debug Bridge. /// The device on which to process command. - public virtual void Deconstruct(out IAdbClient client, out DeviceData device) + public void Deconstruct(out IAdbClient client, out DeviceData device) { client = AdbClient; device = Device; diff --git a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs index 4041e71..9fcb918 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs @@ -19,7 +19,7 @@ public partial class PackageManager /// /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public virtual Task RefreshPackagesAsync(CancellationToken cancellationToken = default) + public Task RefreshPackagesAsync(CancellationToken cancellationToken = default) { ValidateDevice(); @@ -47,7 +47,7 @@ public virtual Task RefreshPackagesAsync(CancellationToken cancellationToken = d /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install. /// A which represents the asynchronous operation. - public virtual async Task InstallPackageAsync(string packageFilePath, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallPackageAsync(string packageFilePath, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -76,7 +76,7 @@ void OnSyncProgressChanged(string? sender, SyncProgressChangedEventArgs args) => /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install. /// A which represents the asynchronous operation. - public virtual async Task InstallRemotePackageAsync(string remoteFilePath, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallRemotePackageAsync(string remoteFilePath, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Installing)); @@ -114,7 +114,7 @@ public virtual async Task InstallRemotePackageAsync(string remoteFilePath, Actio /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultiplePackageAsync(string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultiplePackageAsync(string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -190,7 +190,7 @@ await splitRemoteFilePaths.Select(async x => /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultiplePackageAsync(IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultiplePackageAsync(IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -258,7 +258,7 @@ await splitRemoteFilePaths.Select(async x => /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultipleRemotePackageAsync(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultipleRemotePackageAsync(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.CreateSession)); @@ -307,7 +307,7 @@ await splitRemoteFilePaths.Select(async splitRemoteFilePath => /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultipleRemotePackageAsync(IEnumerable splitRemoteFilePaths, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) + public async Task InstallMultipleRemotePackageAsync(IEnumerable splitRemoteFilePaths, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.CreateSession)); @@ -352,7 +352,7 @@ await splitRemoteFilePaths.Select(async splitRemoteFilePath => /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install. /// A which represents the asynchronous operation. - public virtual async Task InstallPackageAsync(string packageFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + public async Task InstallPackageAsync(string packageFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => await InstallPackageAsync(packageFilePath, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); /// @@ -364,7 +364,7 @@ public virtual async Task InstallPackageAsync(string packageFilePath, IProgress< /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install. /// A which represents the asynchronous operation. - public virtual async Task InstallRemotePackageAsync(string remoteFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + public async Task InstallRemotePackageAsync(string remoteFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => await InstallRemotePackageAsync(remoteFilePath, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); /// @@ -377,7 +377,7 @@ public virtual async Task InstallRemotePackageAsync(string remoteFilePath, IProg /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultiplePackageAsync(string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + public async Task InstallMultiplePackageAsync(string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => await InstallMultiplePackageAsync(basePackageFilePath, splitPackageFilePaths, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); /// @@ -390,7 +390,7 @@ public virtual async Task InstallMultiplePackageAsync(string basePackageFilePath /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultiplePackageAsync(IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + public async Task InstallMultiplePackageAsync(IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => await InstallMultiplePackageAsync(splitPackageFilePaths, packageName, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); /// @@ -403,7 +403,7 @@ public virtual async Task InstallMultiplePackageAsync(IEnumerable splitP /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultipleRemotePackageAsync(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + public async Task InstallMultipleRemotePackageAsync(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => await InstallMultipleRemotePackageAsync(baseRemoteFilePath, splitRemoteFilePaths, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); /// @@ -416,7 +416,7 @@ public virtual async Task InstallMultipleRemotePackageAsync(string baseRemoteFil /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - public virtual async Task InstallMultipleRemotePackageAsync(IEnumerable splitRemoteFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + public async Task InstallMultipleRemotePackageAsync(IEnumerable splitRemoteFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => await InstallMultipleRemotePackageAsync(splitRemoteFilePaths, packageName, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); #endif @@ -436,7 +436,7 @@ public Task UninstallPackageAsync(string packageName, params string[] arguments) /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm uninstall. /// A which represents the asynchronous operation. - public virtual async Task UninstallPackageAsync(string packageName, CancellationToken cancellationToken, params string[] arguments) + public async Task UninstallPackageAsync(string packageName, CancellationToken cancellationToken, params string[] arguments) { ValidateDevice(); @@ -467,7 +467,7 @@ public virtual async Task UninstallPackageAsync(string packageName, Cancellation /// The name of the package from which to get the application version. /// A which can be used to cancel the asynchronous operation. /// A which returns the of target application. - public virtual async Task GetVersionInfoAsync(string packageName, CancellationToken cancellationToken = default) + public async Task GetVersionInfoAsync(string packageName, CancellationToken cancellationToken = default) { ValidateDevice(); @@ -476,6 +476,69 @@ public virtual async Task GetVersionInfoAsync(string packageName, C return receiver.VersionInfo; } + /// + /// Like "install", but starts an install session asynchronously. + /// + /// The absolute package name of the base app. + /// A which can be used to cancel the asynchronous operation. + /// The arguments to pass to pm install-create. + /// A which returns the session ID. + protected async Task CreateInstallSessionAsync(string? packageName = null, CancellationToken cancellationToken = default, params string[] arguments) + { + ValidateDevice(); + + StringBuilder requestBuilder = new StringBuilder().Append("pm install-create"); + + if (!StringExtensions.IsNullOrWhiteSpace(packageName)) + { + _ = requestBuilder.AppendFormat(" -p {0}", packageName); + } + + if (arguments != null) + { + foreach (string argument in arguments) + { + _ = requestBuilder.AppendFormat(" {0}", argument); + } + } + + string cmd = requestBuilder.ToString(); + InstallOutputReceiver receiver = new(); + await AdbClient.ExecuteShellCommandAsync(Device, cmd, receiver, cancellationToken).ConfigureAwait(false); + + if (string.IsNullOrEmpty(receiver.SuccessMessage)) + { + throw new PackageInstallationException(receiver.ErrorMessage); + } + + string result = receiver.SuccessMessage ?? throw new AdbException($"The {nameof(result)} of {nameof(CreateInstallSessionAsync)} is null."); + int arr = result.IndexOf(']') - 1 - result.IndexOf('['); + string session = result.Substring(result.IndexOf('[') + 1, arr); + + return session; + } + + /// + /// Asynchronously write an apk into the given install session. + /// + /// The session ID of the install session. + /// The name of the application. + /// The absolute file path to package file on device. + /// A which can be used to cancel the asynchronous operation. + /// A which represents the asynchronous operation. + protected async Task WriteInstallSessionAsync(string session, string apkName, string path, CancellationToken cancellationToken = default) + { + ValidateDevice(); + + InstallOutputReceiver receiver = new(); + await AdbClient.ExecuteShellCommandAsync(Device, $"pm install-write {session} {apkName}.apk \"{path}\"", receiver, cancellationToken).ConfigureAwait(false); + + if (!string.IsNullOrEmpty(receiver.ErrorMessage)) + { + throw new PackageInstallationException(receiver.ErrorMessage); + } + } + /// /// Asynchronously opens an existing file for reading. /// @@ -549,7 +612,7 @@ protected virtual async Task SyncPackageToDeviceAsync(string localFilePa /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. /// If file removal failed. - protected virtual async Task RemoveRemotePackageAsync(string remoteFilePath, CancellationToken cancellationToken = default) + protected async Task RemoveRemotePackageAsync(string remoteFilePath, CancellationToken cancellationToken = default) { // now we delete the app we synced try @@ -562,69 +625,6 @@ protected virtual async Task RemoveRemotePackageAsync(string remoteFilePath, Can throw; } } - - /// - /// Like "install", but starts an install session asynchronously. - /// - /// The absolute package name of the base app. - /// A which can be used to cancel the asynchronous operation. - /// The arguments to pass to pm install-create. - /// A which returns the session ID. - protected virtual async Task CreateInstallSessionAsync(string? packageName = null, CancellationToken cancellationToken = default, params string[] arguments) - { - ValidateDevice(); - - StringBuilder requestBuilder = new StringBuilder().Append("pm install-create"); - - if (!StringExtensions.IsNullOrWhiteSpace(packageName)) - { - _ = requestBuilder.AppendFormat(" -p {0}", packageName); - } - - if (arguments != null) - { - foreach (string argument in arguments) - { - _ = requestBuilder.AppendFormat(" {0}", argument); - } - } - - string cmd = requestBuilder.ToString(); - InstallOutputReceiver receiver = new(); - await AdbClient.ExecuteShellCommandAsync(Device, cmd, receiver, cancellationToken).ConfigureAwait(false); - - if (string.IsNullOrEmpty(receiver.SuccessMessage)) - { - throw new PackageInstallationException(receiver.ErrorMessage); - } - - string result = receiver.SuccessMessage ?? throw new AdbException($"The {nameof(result)} of {nameof(CreateInstallSessionAsync)} is null."); - int arr = result.IndexOf(']') - 1 - result.IndexOf('['); - string session = result.Substring(result.IndexOf('[') + 1, arr); - - return session; - } - - /// - /// Asynchronously write an apk into the given install session. - /// - /// The session ID of the install session. - /// The name of the application. - /// The absolute file path to package file on device. - /// A which can be used to cancel the asynchronous operation. - /// A which represents the asynchronous operation. - protected virtual async Task WriteInstallSessionAsync(string session, string apkName, string path, CancellationToken cancellationToken = default) - { - ValidateDevice(); - - InstallOutputReceiver receiver = new(); - await AdbClient.ExecuteShellCommandAsync(Device, $"pm install-write {session} {apkName}.apk \"{path}\"", receiver, cancellationToken).ConfigureAwait(false); - - if (!string.IsNullOrEmpty(receiver.ErrorMessage)) - { - throw new PackageInstallationException(receiver.ErrorMessage); - } - } } } #endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs index b6f1367..73182f3 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs @@ -115,7 +115,7 @@ public PackageManager(IAdbClient client, DeviceData device, Func /// Refreshes the packages. /// - public virtual void RefreshPackages() + public void RefreshPackages() { ValidateDevice(); @@ -141,7 +141,7 @@ public virtual void RefreshPackages() /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to adb install. - public virtual void InstallPackage(string packageFilePath, Action? callback = null, params string[] arguments) + public void InstallPackage(string packageFilePath, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -168,7 +168,7 @@ void OnSyncProgressChanged(string? sender, SyncProgressChangedEventArgs args) => /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to adb install. - public virtual void InstallRemotePackage(string remoteFilePath, Action? callback = null, params string[] arguments) + public void InstallRemotePackage(string remoteFilePath, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Installing)); @@ -204,7 +204,7 @@ public virtual void InstallRemotePackage(string remoteFilePath, ActionAn optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultiplePackage(string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, params string[] arguments) + public void InstallMultiplePackage(string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -266,7 +266,7 @@ void OnSplitSyncProgressChanged(string? sender, SyncProgressChangedEventArgs arg /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultiplePackage(IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, params string[] arguments) + public void InstallMultiplePackage(IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.Preparing)); @@ -320,7 +320,7 @@ void OnSyncProgressChanged(string? sender, SyncProgressChangedEventArgs args) /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, Action? callback = null, params string[] arguments) + public void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.CreateSession)); @@ -362,7 +362,7 @@ public virtual void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnu /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultipleRemotePackage(IEnumerable splitRemoteFilePaths, string packageName, Action? callback = null, params string[] arguments) + public void InstallMultipleRemotePackage(IEnumerable splitRemoteFilePaths, string packageName, Action? callback = null, params string[] arguments) { callback?.Invoke(new InstallProgressEventArgs(PackageInstallProgressState.CreateSession)); @@ -400,7 +400,7 @@ public virtual void InstallMultipleRemotePackage(IEnumerable splitRemote /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to adb install. - public virtual void InstallPackage(string packageFilePath, IProgress? progress = null, params string[] arguments) => + public void InstallPackage(string packageFilePath, IProgress? progress = null, params string[] arguments) => InstallPackage(packageFilePath, progress.AsAction(), arguments); /// @@ -410,7 +410,7 @@ public virtual void InstallPackage(string packageFilePath, IProgressAn optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to adb install. - public virtual void InstallRemotePackage(string remoteFilePath, IProgress? progress = null, params string[] arguments) => + public void InstallRemotePackage(string remoteFilePath, IProgress? progress = null, params string[] arguments) => InstallRemotePackage(remoteFilePath, progress.AsAction(), arguments); /// @@ -421,7 +421,7 @@ public virtual void InstallRemotePackage(string remoteFilePath, IProgressAn optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultiplePackage(string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, params string[] arguments) => + public void InstallMultiplePackage(string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, params string[] arguments) => InstallMultiplePackage(basePackageFilePath, splitPackageFilePaths, progress.AsAction(), arguments); /// @@ -432,7 +432,7 @@ public virtual void InstallMultiplePackage(string basePackageFilePath, IEnumerab /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultiplePackage(IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, params string[] arguments) => + public void InstallMultiplePackage(IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, params string[] arguments) => InstallMultiplePackage(splitPackageFilePaths, packageName, progress.AsAction(), arguments); /// @@ -443,7 +443,7 @@ public virtual void InstallMultiplePackage(IEnumerable splitPackageFileP /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, IProgress? progress = null, params string[] arguments) => + public void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, IProgress? progress = null, params string[] arguments) => InstallMultipleRemotePackage(baseRemoteFilePath, splitRemoteFilePaths, progress.AsAction(), arguments); /// @@ -454,7 +454,7 @@ public virtual void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnu /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as , representing the state of installation. /// The arguments to pass to pm install-create. - public virtual void InstallMultipleRemotePackage(IEnumerable splitRemoteFilePaths, string packageName, IProgress? progress = null, params string[] arguments) => + public void InstallMultipleRemotePackage(IEnumerable splitRemoteFilePaths, string packageName, IProgress? progress = null, params string[] arguments) => InstallMultipleRemotePackage(splitRemoteFilePaths, packageName, progress.AsAction(), arguments); #endif @@ -463,7 +463,7 @@ public virtual void InstallMultipleRemotePackage(IEnumerable splitRemote /// /// The name of the package to uninstall. /// The arguments to pass to pm uninstall. - public virtual void UninstallPackage(string packageName, params string[] arguments) + public void UninstallPackage(string packageName, params string[] arguments) { ValidateDevice(); @@ -493,7 +493,7 @@ public virtual void UninstallPackage(string packageName, params string[] argumen /// /// The name of the package from which to get the application version. /// The of target application. - public virtual VersionInfo GetVersionInfo(string packageName) + public VersionInfo GetVersionInfo(string packageName) { ValidateDevice(); @@ -503,13 +503,62 @@ public virtual VersionInfo GetVersionInfo(string packageName) } /// - /// Validates the device is online. + /// Like "install", but starts an install session. /// - protected void ValidateDevice() + /// The absolute package name of the base app. + /// The arguments to pass to pm install-create. + /// Session ID. + protected string CreateInstallSession(string? packageName = null, params string[] arguments) { - if (Device.State != DeviceState.Online) + ValidateDevice(); + + StringBuilder requestBuilder = new StringBuilder().Append("pm install-create"); + + if (!StringExtensions.IsNullOrWhiteSpace(packageName)) { - throw new AdbException("Device is offline"); + _ = requestBuilder.AppendFormat(" -p {0}", packageName); + } + + if (arguments != null) + { + foreach (string argument in arguments) + { + _ = requestBuilder.AppendFormat(" {0}", argument); + } + } + + string cmd = requestBuilder.ToString(); + InstallOutputReceiver receiver = new(); + AdbClient.ExecuteShellCommand(Device, cmd, receiver); + + if (string.IsNullOrEmpty(receiver.SuccessMessage)) + { + throw new PackageInstallationException(receiver.ErrorMessage); + } + + string result = receiver.SuccessMessage ?? throw new AdbException($"The {nameof(result)} of {nameof(CreateInstallSession)} is null."); + int arr = result.IndexOf(']') - 1 - result.IndexOf('['); + string session = result.Substring(result.IndexOf('[') + 1, arr); + + return session; + } + + /// + /// Write an apk into the given install session. + /// + /// The session ID of the install session. + /// The name of the application. + /// The absolute file path to package file on device. + protected void WriteInstallSession(string session, string apkName, string path) + { + ValidateDevice(); + + InstallOutputReceiver receiver = new(); + AdbClient.ExecuteShellCommand(Device, $"pm install-write {session} {apkName}.apk \"{path}\"", receiver); + + if (!string.IsNullOrEmpty(receiver.ErrorMessage)) + { + throw new PackageInstallationException(receiver.ErrorMessage); } } @@ -579,7 +628,7 @@ protected virtual string SyncPackageToDevice(string localFilePath, Action /// Path on device of file to remove. /// If file removal failed. - protected virtual void RemoveRemotePackage(string remoteFilePath) + protected void RemoveRemotePackage(string remoteFilePath) { // now we delete the app we synced try @@ -594,62 +643,13 @@ protected virtual void RemoveRemotePackage(string remoteFilePath) } /// - /// Like "install", but starts an install session. - /// - /// The absolute package name of the base app. - /// The arguments to pass to pm install-create. - /// Session ID. - protected virtual string CreateInstallSession(string? packageName = null, params string[] arguments) - { - ValidateDevice(); - - StringBuilder requestBuilder = new StringBuilder().Append("pm install-create"); - - if (!StringExtensions.IsNullOrWhiteSpace(packageName)) - { - _ = requestBuilder.AppendFormat(" -p {0}", packageName); - } - - if (arguments != null) - { - foreach (string argument in arguments) - { - _ = requestBuilder.AppendFormat(" {0}", argument); - } - } - - string cmd = requestBuilder.ToString(); - InstallOutputReceiver receiver = new(); - AdbClient.ExecuteShellCommand(Device, cmd, receiver); - - if (string.IsNullOrEmpty(receiver.SuccessMessage)) - { - throw new PackageInstallationException(receiver.ErrorMessage); - } - - string result = receiver.SuccessMessage ?? throw new AdbException($"The {nameof(result)} of {nameof(CreateInstallSession)} is null."); - int arr = result.IndexOf(']') - 1 - result.IndexOf('['); - string session = result.Substring(result.IndexOf('[') + 1, arr); - - return session; - } - - /// - /// Write an apk into the given install session. + /// Validates the device is online. /// - /// The session ID of the install session. - /// The name of the application. - /// The absolute file path to package file on device. - protected virtual void WriteInstallSession(string session, string apkName, string path) + protected void ValidateDevice() { - ValidateDevice(); - - InstallOutputReceiver receiver = new(); - AdbClient.ExecuteShellCommand(Device, $"pm install-write {session} {apkName}.apk \"{path}\"", receiver); - - if (!string.IsNullOrEmpty(receiver.ErrorMessage)) + if (Device.State != DeviceState.Online) { - throw new PackageInstallationException(receiver.ErrorMessage); + throw new AdbException("Device is offline"); } } } diff --git a/AdvancedSharpAdbClient/DeviceMonitor.Async.cs b/AdvancedSharpAdbClient/DeviceMonitor.Async.cs index 410a132..2c12ab2 100644 --- a/AdvancedSharpAdbClient/DeviceMonitor.Async.cs +++ b/AdvancedSharpAdbClient/DeviceMonitor.Async.cs @@ -33,7 +33,7 @@ public partial class DeviceMonitor /// [MemberNotNull(nameof(MonitorTask))] - public virtual async Task StartAsync(CancellationToken cancellationToken = default) + public async Task StartAsync(CancellationToken cancellationToken = default) { if (MonitorTask == null) { diff --git a/AdvancedSharpAdbClient/DeviceMonitor.cs b/AdvancedSharpAdbClient/DeviceMonitor.cs index 02ef64d..4ac331c 100644 --- a/AdvancedSharpAdbClient/DeviceMonitor.cs +++ b/AdvancedSharpAdbClient/DeviceMonitor.cs @@ -152,7 +152,7 @@ public DeviceMonitor(IAdbSocket socket, ILogger? logger = null) nameof(MonitorThread) #endif )] - public virtual void Start() + public void Start() { #if HAS_TASK if (MonitorTask == null) diff --git a/AdvancedSharpAdbClient/Models/Framebuffer.cs b/AdvancedSharpAdbClient/Models/Framebuffer.cs index 15c3a9d..d84cca0 100644 --- a/AdvancedSharpAdbClient/Models/Framebuffer.cs +++ b/AdvancedSharpAdbClient/Models/Framebuffer.cs @@ -15,7 +15,7 @@ namespace AdvancedSharpAdbClient.Models /// The device for which to fetch the frame buffer. /// The at which the adb server is listening. /// The to create . - public class Framebuffer(DeviceData device, EndPoint endPoint, Func adbSocketFactory) : IDisposable + public sealed class Framebuffer(DeviceData device, EndPoint endPoint, Func adbSocketFactory) : IDisposable { /// /// The of s which contains the framebuffer header. @@ -35,7 +35,7 @@ public class Framebuffer(DeviceData device, EndPoint endPoint, Func /// The to create . /// - protected readonly Func AdbSocketFactory = adbSocketFactory; + private readonly Func AdbSocketFactory = adbSocketFactory; /// /// Initializes a new instance of the class. @@ -100,7 +100,7 @@ public Framebuffer(DeviceData device) : this(device, AdbClient.DefaultEndPoint, /// /// Refreshes the header of framebuffer when . [MemberNotNull(nameof(Data))] - public virtual void Refresh(bool reset = false) + public void Refresh(bool reset = false) { EnsureNotDisposed(); @@ -152,7 +152,7 @@ public virtual void Refresh(bool reset = false) /// Refreshes the header of framebuffer when . /// A which can be used to cancel the asynchronous task. /// A which represents the asynchronous operation. - public virtual async Task RefreshAsync(bool reset = false, CancellationToken cancellationToken = default) + public async Task RefreshAsync(bool reset = false, CancellationToken cancellationToken = default) { EnsureNotDisposed(); @@ -205,7 +205,7 @@ public virtual async Task RefreshAsync(bool reset = false, CancellationToken can #if NET [SupportedOSPlatform("windows")] #endif - public virtual Bitmap? ToImage() + public Bitmap? ToImage() { EnsureNotDisposed(); return Data == null ? throw new InvalidOperationException($"Call {nameof(Refresh)} first") : Header.ToImage(Data); @@ -230,7 +230,7 @@ public virtual async Task RefreshAsync(bool reset = false, CancellationToken can /// /// A which can be used to cancel the asynchronous task. /// An which represents the framebuffer data. - public virtual Task ToBitmapAsync(CancellationToken cancellationToken = default) + public Task ToBitmapAsync(CancellationToken cancellationToken = default) { EnsureNotDisposed(); return Data == null ? throw new InvalidOperationException($"Call {nameof(RefreshAsync)} first") : Header.ToBitmapAsync(Data, cancellationToken); @@ -242,7 +242,7 @@ public virtual async Task RefreshAsync(bool reset = false, CancellationToken can /// The target to invoke the code on. /// A which can be used to cancel the asynchronous task. /// An which represents the framebuffer data. - public virtual Task ToBitmapAsync(CoreDispatcher dispatcher, CancellationToken cancellationToken = default) + public Task ToBitmapAsync(CoreDispatcher dispatcher, CancellationToken cancellationToken = default) { EnsureNotDisposed(); return Data == null ? throw new InvalidOperationException($"Call {nameof(RefreshAsync)} first") : Header.ToBitmapAsync(Data, dispatcher, cancellationToken); @@ -254,7 +254,7 @@ public virtual async Task RefreshAsync(bool reset = false, CancellationToken can /// The target to invoke the code on. /// A which can be used to cancel the asynchronous task. /// An which represents the framebuffer data. - public virtual Task ToBitmapAsync(DispatcherQueue dispatcher, CancellationToken cancellationToken = default) + public Task ToBitmapAsync(DispatcherQueue dispatcher, CancellationToken cancellationToken = default) { EnsureNotDisposed(); return Data == null ? throw new InvalidOperationException($"Call {nameof(RefreshAsync)} first") : Header.ToBitmapAsync(Data, dispatcher, cancellationToken); @@ -262,7 +262,7 @@ public virtual async Task RefreshAsync(bool reset = false, CancellationToken can #endif /// - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { if (!disposed && disposing) { @@ -288,6 +288,6 @@ public void Dispose() /// /// Throws an exception if this has been disposed. /// - protected virtual void EnsureNotDisposed() => ExceptionExtensions.ThrowIf(disposed, this); + private void EnsureNotDisposed() => ExceptionExtensions.ThrowIf(disposed, this); } } diff --git a/AdvancedSharpAdbClient/SyncService.Async.cs b/AdvancedSharpAdbClient/SyncService.Async.cs index 3a33def..ab627a6 100644 --- a/AdvancedSharpAdbClient/SyncService.Async.cs +++ b/AdvancedSharpAdbClient/SyncService.Async.cs @@ -17,7 +17,7 @@ public partial class SyncService /// This method has been invoked by the constructor. /// Do not use it unless you have closed the connection. /// Use to reopen the connection. - public virtual async Task OpenAsync(CancellationToken cancellationToken = default) + public async Task OpenAsync(CancellationToken cancellationToken = default) { // target a specific device await Socket.SetDeviceAsync(Device, cancellationToken).ConfigureAwait(false); @@ -27,7 +27,7 @@ public virtual async Task OpenAsync(CancellationToken cancellationToken = defaul } /// - public virtual async Task ReopenAsync(CancellationToken cancellationToken = default) + public async Task ReopenAsync(CancellationToken cancellationToken = default) { await Socket.ReconnectAsync(true, cancellationToken).ConfigureAwait(false); await OpenAsync(cancellationToken).ConfigureAwait(false); @@ -341,7 +341,7 @@ public virtual async Task PullAsync(string remotePath, IOutputStream stream, Act #endif /// - public virtual async Task StatAsync(string remotePath, CancellationToken cancellationToken = default) + public async Task StatAsync(string remotePath, CancellationToken cancellationToken = default) { // create the stat request message. await Socket.SendSyncRequestAsync(SyncCommand.STAT, remotePath, cancellationToken).ConfigureAwait(false); @@ -361,7 +361,7 @@ public virtual async Task StatAsync(string remotePath, Cancellat } /// - public virtual async Task> GetDirectoryListingAsync(string remotePath, CancellationToken cancellationToken = default) + public async Task> GetDirectoryListingAsync(string remotePath, CancellationToken cancellationToken = default) { bool isLocked = false; @@ -401,7 +401,7 @@ public virtual async Task> GetDirectoryListingAsync(string #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER /// - public virtual async IAsyncEnumerable GetDirectoryAsyncListing(string remotePath, [EnumeratorCancellation] CancellationToken cancellationToken = default) + public async IAsyncEnumerable GetDirectoryAsyncListing(string remotePath, [EnumeratorCancellation] CancellationToken cancellationToken = default) { bool isLocked = false; diff --git a/AdvancedSharpAdbClient/SyncService.cs b/AdvancedSharpAdbClient/SyncService.cs index 72c130c..7d09fab 100644 --- a/AdvancedSharpAdbClient/SyncService.cs +++ b/AdvancedSharpAdbClient/SyncService.cs @@ -112,7 +112,7 @@ public SyncService(IAdbSocket socket, DeviceData device) /// This method has been invoked by the constructor. /// Do not use it unless you have closed the connection. /// Use to reopen the connection. - public virtual void Open() + public void Open() { // target a specific device Socket.SetDevice(Device); @@ -122,7 +122,7 @@ public virtual void Open() } /// - public virtual void Reopen() + public void Reopen() { Socket.Reconnect(true); Open(); @@ -272,7 +272,7 @@ public virtual void Pull(string remoteFilePath, Stream stream, Action - public virtual FileStatistics Stat(string remotePath) + public FileStatistics Stat(string remotePath) { // create the stat request message. Socket.SendSyncRequest(SyncCommand.STAT, remotePath); @@ -292,7 +292,7 @@ public virtual FileStatistics Stat(string remotePath) } /// - public virtual IEnumerable GetDirectoryListing(string remotePath) + public IEnumerable GetDirectoryListing(string remotePath) { bool isLocked = false; diff --git a/AdvancedSharpAdbClient/TcpSocket.Async.cs b/AdvancedSharpAdbClient/TcpSocket.Async.cs index 557afe0..0637543 100644 --- a/AdvancedSharpAdbClient/TcpSocket.Async.cs +++ b/AdvancedSharpAdbClient/TcpSocket.Async.cs @@ -15,7 +15,7 @@ public partial class TcpSocket { /// [MemberNotNull(nameof(EndPoint))] - public virtual async Task ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken = default) + public async Task ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken = default) { if (endPoint is not (IPEndPoint or DnsEndPoint)) { @@ -32,7 +32,7 @@ public virtual async Task ConnectAsync(EndPoint endPoint, CancellationToken canc } /// - public virtual Task ReconnectAsync(bool isForce, CancellationToken cancellationToken = default) + public Task ReconnectAsync(bool isForce, CancellationToken cancellationToken = default) { if (isForce || !Socket.Connected) { @@ -56,7 +56,7 @@ public virtual Task ReconnectAsync(bool isForce, CancellationToken cancellationT public Task ReconnectAsync(CancellationToken cancellationToken = default) => ReconnectAsync(false, cancellationToken); /// - public virtual Task SendAsync(byte[] buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => + public Task SendAsync(byte[] buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => #if NET6_0_OR_GREATER Socket.SendAsync(buffer, socketFlags, cancellationToken).AsTask(); #else @@ -64,15 +64,15 @@ public virtual Task SendAsync(byte[] buffer, SocketFlags socketFlags, Cance #endif /// - public virtual Task SendAsync(byte[] buffer, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => + public Task SendAsync(byte[] buffer, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => Socket.SendAsync(buffer, size, socketFlags, cancellationToken); /// - public virtual Task SendAsync(byte[] buffer, int offset, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => + public Task SendAsync(byte[] buffer, int offset, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => Socket.SendAsync(buffer, offset, size, socketFlags, cancellationToken); /// - public virtual Task ReceiveAsync(byte[] buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => + public Task ReceiveAsync(byte[] buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => #if NET6_0_OR_GREATER Socket.ReceiveAsync(buffer, socketFlags, cancellationToken).AsTask(); #else @@ -80,11 +80,11 @@ public virtual Task ReceiveAsync(byte[] buffer, SocketFlags socketFlags, Ca #endif /// - public virtual Task ReceiveAsync(byte[] buffer, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => + public Task ReceiveAsync(byte[] buffer, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => Socket.ReceiveAsync(buffer, size, socketFlags, cancellationToken); /// - public virtual Task ReceiveAsync(byte[] buffer, int offset, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => + public Task ReceiveAsync(byte[] buffer, int offset, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => Socket.ReceiveAsync(buffer, offset, size, socketFlags, cancellationToken); #if HAS_BUFFERS diff --git a/AdvancedSharpAdbClient/TcpSocket.cs b/AdvancedSharpAdbClient/TcpSocket.cs index c81c7a1..8a0b2fe 100644 --- a/AdvancedSharpAdbClient/TcpSocket.cs +++ b/AdvancedSharpAdbClient/TcpSocket.cs @@ -13,7 +13,7 @@ namespace AdvancedSharpAdbClient /// /// Implements the interface using the standard class. /// - public partial class TcpSocket : ITcpSocket + public sealed partial class TcpSocket : ITcpSocket { /// /// Initializes a new instance of the class. @@ -23,12 +23,12 @@ public partial class TcpSocket : ITcpSocket /// /// The underlying socket that manages the connection. /// - public Socket Socket { get; protected set; } + public Socket Socket { get; private set; } /// /// The at which the socket is listening. /// - public EndPoint? EndPoint { get; protected set; } + public EndPoint? EndPoint { get; private set; } /// public bool Connected => Socket.Connected; @@ -42,7 +42,7 @@ public int ReceiveBufferSize /// [MemberNotNull(nameof(EndPoint))] - public virtual void Connect(EndPoint endPoint) + public void Connect(EndPoint endPoint) { if (endPoint is not (IPEndPoint or DnsEndPoint)) { @@ -55,7 +55,7 @@ public virtual void Connect(EndPoint endPoint) } /// - public virtual void Reconnect(bool isForce = false) + public void Reconnect(bool isForce = false) { if (isForce || !Socket.Connected) { @@ -71,7 +71,7 @@ public virtual void Reconnect(bool isForce = false) } /// - protected virtual void Dispose(bool disposing) + private void Dispose(bool disposing) { if (disposing) { @@ -87,43 +87,43 @@ public void Dispose() } /// - public virtual void Close() => Socket.Close(); + public void Close() => Socket.Close(); /// - public virtual int Send(byte[] buffer, SocketFlags socketFlags) => + public int Send(byte[] buffer, SocketFlags socketFlags) => Socket.Send(buffer, socketFlags); /// - public virtual int Send(byte[] buffer, int size, SocketFlags socketFlags) => + public int Send(byte[] buffer, int size, SocketFlags socketFlags) => Socket.Send(buffer, size, socketFlags); /// - public virtual int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags) => + public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags) => Socket.Send(buffer, offset, size, socketFlags); /// - public virtual int Receive(byte[] buffer, SocketFlags socketFlags) => + public int Receive(byte[] buffer, SocketFlags socketFlags) => Socket.Receive(buffer, socketFlags); /// - public virtual int Receive(byte[] buffer, int size, SocketFlags socketFlags) => + public int Receive(byte[] buffer, int size, SocketFlags socketFlags) => Socket.Receive(buffer, size, socketFlags); /// - public virtual int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags) => + public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags) => Socket.Receive(buffer, offset, size, socketFlags); #if HAS_BUFFERS /// - public virtual int Send(ReadOnlySpan buffer, SocketFlags socketFlags) => + public int Send(ReadOnlySpan buffer, SocketFlags socketFlags) => Socket.Send(buffer, socketFlags); /// - public virtual int Receive(Span buffer, SocketFlags socketFlags) => + public int Receive(Span buffer, SocketFlags socketFlags) => Socket.Receive(buffer, socketFlags); #endif /// - public virtual Stream GetStream() => new NetworkStream(Socket); + public Stream GetStream() => new NetworkStream(Socket); } } From a7e0afe7e115130ac7a03d5fe6a6424392bdb8a7 Mon Sep 17 00:00:00 2001 From: wherewhere Date: Thu, 1 Feb 2024 23:52:07 +0800 Subject: [PATCH 4/6] Make TcpSocket and Models sealed --- AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs | 8 ++++---- AdvancedSharpAdbClient/Models/DeviceData.cs | 2 +- AdvancedSharpAdbClient/Models/ForwardData.cs | 2 +- .../Models/InstallProgress.EventArgs.cs | 2 +- AdvancedSharpAdbClient/Models/SyncService.EventArgs.cs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs b/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs index 5658127..9b33785 100644 --- a/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs +++ b/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs @@ -11,7 +11,7 @@ namespace AdvancedSharpAdbClient.Models /// The event arguments that are passed when a device event occurs. /// /// The device. - public class DeviceDataEventArgs(DeviceData device) : EventArgs + public abstract class DeviceDataEventArgs(DeviceData device) : EventArgs { /// /// Gets the device where the change occurred. @@ -24,7 +24,7 @@ public class DeviceDataEventArgs(DeviceData device) : EventArgs /// The event arguments that are passed when a device event occurs. /// /// The list of device. - public class DeviceDataNotifyEventArgs(IEnumerable devices) : EventArgs + public sealed class DeviceDataNotifyEventArgs(IEnumerable devices) : EventArgs { /// /// Gets the list of device where the change occurred. @@ -38,7 +38,7 @@ public class DeviceDataNotifyEventArgs(IEnumerable devices) : EventA /// /// The device. /// The device after the reported change. - public class DeviceDataConnectEventArgs(DeviceData device, bool isConnect) : DeviceDataEventArgs(device) + public sealed class DeviceDataConnectEventArgs(DeviceData device, bool isConnect) : DeviceDataEventArgs(device) { /// /// Gets the connect state of the device after the reported change. @@ -52,7 +52,7 @@ public class DeviceDataConnectEventArgs(DeviceData device, bool isConnect) : Dev /// The device. /// The state of the device after the reported change. /// The state of the device before the reported change. - public class DeviceDataChangeEventArgs(DeviceData device, DeviceState newState, DeviceState oldState) : DeviceDataEventArgs(device) + public sealed class DeviceDataChangeEventArgs(DeviceData device, DeviceState newState, DeviceState oldState) : DeviceDataEventArgs(device) { /// /// Gets the state of the device after the reported change. diff --git a/AdvancedSharpAdbClient/Models/DeviceData.cs b/AdvancedSharpAdbClient/Models/DeviceData.cs index 13c7c78..39b74a2 100644 --- a/AdvancedSharpAdbClient/Models/DeviceData.cs +++ b/AdvancedSharpAdbClient/Models/DeviceData.cs @@ -11,7 +11,7 @@ namespace AdvancedSharpAdbClient.Models /// /// Represents a device that is connected to the Android Debug Bridge. /// - public partial class DeviceData : IEquatable + public sealed partial class DeviceData : IEquatable { /// /// A regular expression that can be used to parse the device information that is returned by the Android Debut Bridge. diff --git a/AdvancedSharpAdbClient/Models/ForwardData.cs b/AdvancedSharpAdbClient/Models/ForwardData.cs index 2bbf793..b5a6e51 100644 --- a/AdvancedSharpAdbClient/Models/ForwardData.cs +++ b/AdvancedSharpAdbClient/Models/ForwardData.cs @@ -10,7 +10,7 @@ namespace AdvancedSharpAdbClient.Models /// /// Contains information about port forwarding configured by the Android Debug Bridge. /// - public class ForwardData : IEquatable + public sealed class ForwardData : IEquatable { /// /// Initializes a new instance of the class. diff --git a/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs b/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs index bc3b974..7d8d869 100644 --- a/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs +++ b/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs @@ -10,7 +10,7 @@ namespace AdvancedSharpAdbClient.Models /// Represents the state of apk installation. /// /// The state of the installation. - public class InstallProgressEventArgs(PackageInstallProgressState state) : EventArgs + public sealed class InstallProgressEventArgs(PackageInstallProgressState state) : EventArgs { /// /// Gets the state of the installation. diff --git a/AdvancedSharpAdbClient/Models/SyncService.EventArgs.cs b/AdvancedSharpAdbClient/Models/SyncService.EventArgs.cs index fe6df0b..528b7e1 100644 --- a/AdvancedSharpAdbClient/Models/SyncService.EventArgs.cs +++ b/AdvancedSharpAdbClient/Models/SyncService.EventArgs.cs @@ -9,7 +9,7 @@ namespace AdvancedSharpAdbClient.Models /// /// Provides data for the interface. /// - public class SyncProgressChangedEventArgs(long current, long total) : EventArgs + public sealed class SyncProgressChangedEventArgs(long current, long total) : EventArgs { /// /// Gets the number of bytes sync to the local computer. From 19d7683d2c2398ea09021aff3e50e0a64357bf9d Mon Sep 17 00:00:00 2001 From: wherewhere Date: Fri, 2 Feb 2024 20:10:17 +0800 Subject: [PATCH 5/6] Bring back Cords and Area --- .../DeviceCommands/DeviceClientTexts.Async.cs | 10 +- .../DeviceCommands/DeviceClientTexts.cs | 8 +- .../DeviceCommands/Models/AreaTests.cs | 304 ++++++++++++++++ .../DeviceCommands/Models/CordsTests.cs | 224 ++++++++++++ .../AdvancedSharpAdbClient.csproj | 4 +- .../DeviceCommands/DeviceClient.Async.cs | 8 +- .../DeviceCommands/DeviceClient.cs | 10 +- .../DeviceCommands/DeviceExtensions.Async.cs | 6 +- .../DeviceCommands/DeviceExtensions.cs | 10 +- .../DeviceCommands/Models/Area.cs | 331 ++++++++++++++++++ .../DeviceCommands/Models/Cords.cs | 215 ++++++++++++ .../DeviceCommands/Models/Element.cs | 14 +- AdvancedSharpAdbClient/Models/Framebuffer.cs | 1 + .../Models/FramebufferHeader.cs | 1 + AdvancedSharpAdbClient/Polyfills/Point.cs | 9 +- AdvancedSharpAdbClient/Polyfills/Rectangle.cs | 7 +- .../Properties/GlobalUsings.cs | 10 +- 17 files changed, 1121 insertions(+), 51 deletions(-) create mode 100644 AdvancedSharpAdbClient.Tests/DeviceCommands/Models/AreaTests.cs create mode 100644 AdvancedSharpAdbClient.Tests/DeviceCommands/Models/CordsTests.cs create mode 100644 AdvancedSharpAdbClient/DeviceCommands/Models/Area.cs create mode 100644 AdvancedSharpAdbClient/DeviceCommands/Models/Cords.cs diff --git a/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.Async.cs b/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.Async.cs index c7b47f9..5209ea9 100644 --- a/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.Async.cs +++ b/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.Async.cs @@ -189,7 +189,7 @@ at android.os.Binder.execTransactInternal(Binder.java:1165) } /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void ClickCordsAsyncTest() @@ -219,7 +219,7 @@ public async void SwipeAsyncTest() } /// - /// Tests the method. + /// Tests the method. /// [Fact] public async void SwipePointAsyncTest() @@ -355,7 +355,7 @@ public async void FindElementAsyncTest() Assert.Equal("android.widget.TextView", child.Class); Assert.Equal("com.bilibili.app.in", child.Package); Assert.Equal("com.bilibili.app.in:id/header_info_name", child.ResourceID); - Assert.Equal(Rectangle.FromLTRB(45, 889, 427, 973), child.Bounds); + Assert.Equal(Area.FromLTRB(45, 889, 427, 973), child.Bounds); Assert.Equal(child, element.FindDescendantOrSelf(x => x.Text == "where-where")); Assert.Equal(2, element.FindDescendants().Where(x => x.Text == "where-where").Count()); } @@ -379,7 +379,7 @@ public async void FindElementsAsyncTest() Assert.Equal(145, childCount); Element element = elements[0][0][0][0][0][0][0][0][0][2][1][0][0]; Assert.Equal("where-where", element.Text); - Assert.Equal(Rectangle.FromLTRB(45, 889, 427, 973), element.Bounds); + Assert.Equal(Area.FromLTRB(45, 889, 427, 973), element.Bounds); } /// @@ -401,7 +401,7 @@ public async void FindAsyncElementsTest() Assert.Equal(145, childCount); Element element = elements[0][0][0][0][0][0][0][0][0][2][1][0][0]; Assert.Equal("where-where", element.Text); - Assert.Equal(Rectangle.FromLTRB(45, 889, 427, 973), element.Bounds); + Assert.Equal(Area.FromLTRB(45, 889, 427, 973), element.Bounds); } /// diff --git a/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs b/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs index 6e175e6..32968a0 100644 --- a/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs +++ b/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs @@ -203,7 +203,7 @@ at android.os.Binder.execTransactInternal(Binder.java:1165) } /// - /// Tests the method. + /// Tests the method. /// [Fact] public void ClickCordsTest() @@ -233,7 +233,7 @@ public void SwipeTest() } /// - /// Tests the method. + /// Tests the method. /// [Fact] public void SwipePointTest() @@ -369,7 +369,7 @@ public void FindElementTest() Assert.Equal("android.widget.TextView", child.Class); Assert.Equal("com.bilibili.app.in", child.Package); Assert.Equal("com.bilibili.app.in:id/header_info_name", child.ResourceID); - Assert.Equal(Rectangle.FromLTRB(45, 889, 427, 973), child.Bounds); + Assert.Equal(Area.FromLTRB(45, 889, 427, 973), child.Bounds); Assert.Equal(child, element.FindDescendantOrSelf(x => x.Text == "where-where")); Assert.Equal(2, element.FindDescendants().Where(x => x.Text == "where-where").Count()); } @@ -393,7 +393,7 @@ public void FindElementsTest() Assert.Equal(145, childCount); Element element = elements[0][0][0][0][0][0][0][0][0][2][1][0][0]; Assert.Equal("where-where", element.Text); - Assert.Equal(Rectangle.FromLTRB(45, 889, 427, 973), element.Bounds); + Assert.Equal(Area.FromLTRB(45, 889, 427, 973), element.Bounds); } /// diff --git a/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/AreaTests.cs b/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/AreaTests.cs new file mode 100644 index 0000000..57fca04 --- /dev/null +++ b/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/AreaTests.cs @@ -0,0 +1,304 @@ +using System; +using System.Drawing; +using System.Globalization; +using Xunit; + +namespace AdvancedSharpAdbClient.DeviceCommands.Models.Tests +{ + /// + /// Tests the struct. + /// + public class AreaTests + { + [Fact] + public void DefaultConstructorTest() + { + Assert.Equal(Area.Empty, new Area()); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, 0, 0, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + public void NonDefaultConstructorTest(int x, int y, int width, int height) + { + Area rect1 = new(x, y, width, height); + Area rect2 = new Rectangle(new Point(x, y), new Size(width, height)); + + Assert.Equal(rect1, rect2); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, 0, 0, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + public void FromLTRBTest(int left, int top, int right, int bottom) + { + Area rect1 = new(left, top, unchecked(right - left), unchecked(bottom - top)); + Area rect2 = Area.FromLTRB(left, top, right, bottom); + + Assert.Equal(rect1, rect2); + } + + [Fact] + public void EmptyTest() + { + Assert.True(Area.Empty.IsEmpty); + Assert.True(new Area(0, 0, 0, 0).IsEmpty); + Assert.True(new Area().IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + public void NonEmptyTest(int x, int y, int width, int height) + { + Assert.False(new Area(x, y, width, height).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, 0, 0, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + [InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] + public void DimensionsTest(int x, int y, int width, int height) + { + Area rect = new(x, y, width, height); + Assert.Equal(new Cords(x, y), rect.Location); + Assert.Equal(new Size(width, height), rect.Rectangle.Size); + + Assert.Equal(x, rect.X); + Assert.Equal(y, rect.Y); + Assert.Equal(width, rect.Width); + Assert.Equal(height, rect.Height); + Assert.Equal(x, rect.Left); + Assert.Equal(y, rect.Top); + Assert.Equal(unchecked(x + width), rect.Right); + Assert.Equal(unchecked(y + height), rect.Bottom); + + Cords p = new(width, height); + Size s = new(x, y); + rect.Location = p; + rect.rectangle.Size = s; + + Assert.Equal(p, rect.Location); + Assert.Equal(s, rect.Rectangle.Size); + + Assert.Equal(width, rect.X); + Assert.Equal(height, rect.Y); + Assert.Equal(x, rect.Width); + Assert.Equal(y, rect.Height); + Assert.Equal(width, rect.Left); + Assert.Equal(height, rect.Top); + Assert.Equal(unchecked(x + width), rect.Right); + Assert.Equal(unchecked(y + height), rect.Bottom); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(int.MaxValue, int.MinValue)] + public static void LocationSetTest(int x, int y) + { + Cords Cords = new(x, y); + Area rect = new(10, 10, 10, 10) + { + Location = Cords + }; + Assert.Equal(Cords, rect.Location); + Assert.Equal(Cords.X, rect.X); + Assert.Equal(Cords.Y, rect.Y); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(int.MaxValue, int.MinValue)] + public static void SizeSetTest(int x, int y) + { + Size size = new(x, y); + Area rect = new Rectangle(10, 10, 10, 10) + { + Size = size + }; + Assert.Equal(size, rect.Rectangle.Size); + Assert.Equal(size.Width, rect.Width); + Assert.Equal(size.Height, rect.Height); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + [InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] + public void EqualityTest(int x, int y, int width, int height) + { + Area rect1 = new(x, y, width, height); + Area rect2 = new(width / 2, height / 2, x, y); + + Assert.True(rect1 != rect2); + Assert.False(rect1 == rect2); + Assert.False(rect1.Equals(rect2)); + Assert.False(rect1.Equals((object)rect2)); + } + + [Fact] + public static void EqualityTest_NotArea() + { + Area Area = new(0, 0, 0, 0); + Assert.False(Area.Equals(null)); + Assert.False(Area.Equals(0)); + Assert.False(Area.Equals(new RectangleF(0, 0, 0, 0))); + } + + [Fact] + public static void GetHashCodeTest() + { + Area rect1 = new(10, 10, 10, 10); + Area rect2 = new(10, 10, 10, 10); + Assert.Equal(rect1.GetHashCode(), rect2.GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Area(20, 10, 10, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Area(10, 20, 10, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Area(10, 10, 20, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Area(10, 10, 10, 20).GetHashCode()); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MaxValue, float.MinValue, float.MaxValue)] + [InlineData(0, 0, 0, 0)] + public void AreaFConversionTest(float x, float y, float width, float height) + { + RectangleF rect = new(x, y, width, height); + Area rCeiling, rTruncate, rRound; + + unchecked + { + rCeiling = new Area((int)Math.Ceiling(x), (int)Math.Ceiling(y), + (int)Math.Ceiling(width), (int)Math.Ceiling(height)); + rTruncate = new Area((int)x, (int)y, (int)width, (int)height); + rRound = new Area((int)Math.Round(x), (int)Math.Round(y), + (int)Math.Round(width), (int)Math.Round(height)); + } + + Assert.Equal(rCeiling, Rectangle.Ceiling(rect)); + Assert.Equal(rTruncate, Rectangle.Truncate(rect)); + Assert.Equal(rRound, Rectangle.Round(rect)); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void ContainsTest(int x, int y, int width, int height) + { + Area rect = new(unchecked((2 * x) - width), unchecked((2 * y) - height), width, height); + Cords p = new(x, y); + Area r = new(x, y, width / 2, height / 2); + + Assert.False(rect.Contains(x, y)); + Assert.False(rect.Contains(p)); + Assert.False(rect.Contains(r)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void InflateTest(int x, int y, int width, int height) + { + Area inflatedRect, rect = new(x, y, width, height); + unchecked + { + inflatedRect = new Area(x - width, y - height, width + (2 * width), height + (2 * height)); + } + + Assert.Equal(inflatedRect, Area.Inflate(rect, width, height)); + + rect.Inflate(width, height); + Assert.Equal(inflatedRect, rect); + + Size s = new(x, y); + unchecked + { + inflatedRect = new Area(rect.X - x, rect.Y - y, rect.Width + (2 * x), rect.Height + (2 * y)); + } + + rect.rectangle.Inflate(s); + Assert.Equal(inflatedRect, rect); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void IntersectTest(int x, int y, int width, int height) + { + Area rect = new(x, y, width, height); + Area expectedRect = Area.Intersect(rect, rect); + rect.Intersect(rect); + Assert.Equal(expectedRect, rect); + Assert.False(rect.IntersectsWith(expectedRect)); + } + + [Fact] + public static void Intersect_IntersectingAreas_Test() + { + Area rect1 = new(0, 0, 5, 5); + Area rect2 = new(1, 1, 3, 3); + Area expected = new(1, 1, 3, 3); + + Assert.Equal(expected, Area.Intersect(rect1, rect2)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(int.MaxValue, 0, 0, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void UnionTest(int x, int y, int width, int height) + { + Area a = new(x, y, width, height); + Area b = new(width, height, x, y); + + int x1 = Math.Min(a.X, b.X); + int x2 = Math.Max(a.X + a.Width, b.X + b.Width); + int y1 = Math.Min(a.Y, b.Y); + int y2 = Math.Max(a.Y + a.Height, b.Y + b.Height); + + Area expectedArea = new(x1, y1, x2 - x1, y2 - y1); + + Assert.Equal(expectedArea, Area.Union(a, b)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(int.MaxValue, 0, 0, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void OffsetTest(int x, int y, int width, int height) + { + Area r1 = new(x, y, width, height); + Area expectedRect = new(x + width, y + height, width, height); + Cords p = new(width, height); + + r1.Offset(p); + Assert.Equal(expectedRect, r1); + + expectedRect.Offset(p); + r1.Offset(width, height); + Assert.Equal(expectedRect, r1); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(5, -5, 0, 1)] + public void ToStringTest(int x, int y, int width, int height) + { + Area r = new(x, y, width, height); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "{{X={0},Y={1},Width={2},Height={3}}}", r.X, r.Y, r.Width, r.Height), r.ToString()); + } + } +} diff --git a/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/CordsTests.cs b/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/CordsTests.cs new file mode 100644 index 0000000..943466c --- /dev/null +++ b/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/CordsTests.cs @@ -0,0 +1,224 @@ +using System; +using System.Drawing; +using System.Globalization; +using Xunit; + +namespace AdvancedSharpAdbClient.DeviceCommands.Models.Tests +{ + /// + /// Tests the struct. + /// + public class CordsTests + { + [Fact] + public void DefaultConstructorTest() + { + Assert.Equal(Cords.Empty, new Cords()); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void NonDefaultConstructorTest(int x, int y) + { + Cords p1 = new(x, y); + Cords p2 = new Point(new Size(x, y)); + + Assert.Equal(p1, p2); + } + + [Theory] + [InlineData(int.MaxValue)] + [InlineData(int.MinValue)] + [InlineData(0)] + public void SingleIntConstructorTest(int x) + { + Cords p1 = new(x); + Cords p2 = new(unchecked((short)(x & 0xFFFF)), unchecked((short)((x >> 16) & 0xFFFF))); + + Assert.Equal(p1, p2); + } + + [Fact] + public void IsEmptyDefaultsTest() + { + Assert.True(Cords.Empty.IsEmpty); + Assert.True(new Cords().IsEmpty); + Assert.True(new Cords(0, 0).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + public void IsEmptyRandomTest(int x, int y) + { + Assert.False(new Cords(x, y).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void CoordinatesTest(int x, int y) + { + Cords p = new(x, y); + Assert.Equal(x, p.X); + Assert.Equal(y, p.Y); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void CordsFConversionTest(int x, int y) + { + PointF p = new Cords(x, y).Point; + Assert.Equal(new PointF(x, y), p); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void SizeConversionTest(int x, int y) + { + Size sz = (Size)new Cords(x, y).Point; + Assert.Equal(new Size(x, y), sz); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void ArithmeticTest(int x, int y) + { + Cords addExpected, subExpected, p = new(x, y); + Size s = new(y, x); + + unchecked + { + addExpected = new Cords(x + y, y + x); + subExpected = new Cords(x - y, y - x); + } + + Assert.Equal(addExpected, p.Point + s); + Assert.Equal(subExpected, p.Point - s); + Assert.Equal(addExpected, Point.Add(p, s)); + Assert.Equal(subExpected, Point.Subtract(p, s)); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void CordsFMathematicalTest(float x, float y) + { + PointF pf = new(x, y); + Cords pCeiling, pTruncate, pRound; + + unchecked + { + pCeiling = new Cords((int)Math.Ceiling(x), (int)Math.Ceiling(y)); + pTruncate = new Cords((int)x, (int)y); + pRound = new Cords((int)Math.Round(x), (int)Math.Round(y)); + } + + Assert.Equal(pCeiling, Point.Ceiling(pf)); + Assert.Equal(pRound, Point.Round(pf)); + Assert.Equal(pTruncate, Point.Truncate(pf)); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void OffsetTest(int x, int y) + { + Cords p1 = new(x, y); + Cords p2 = new(y, x); + + p1.Offset(p2); + + Assert.Equal(unchecked(p2.X + p2.Y), p1.X); + Assert.Equal(p1.X, p1.Y); + + p2.Offset(x, y); + Assert.Equal(p1, p2); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void EqualityTest(int x, int y) + { + Cords p1 = new(x, y); + Cords p2 = new((x / 2) - 1, (y / 2) - 1); + Cords p3 = new(x, y); + + Assert.True(p1 == p3); + Assert.True(p1 != p2); + Assert.True(p2 != p3); + + Assert.True(p1.Equals(p3)); + Assert.False(p1.Equals(p2)); + Assert.False(p2.Equals(p3)); + + Assert.True(p1.Equals((object)p3)); + Assert.False(p1.Equals((object)p2)); + Assert.False(p2.Equals((object)p3)); + + Assert.Equal(p1.GetHashCode(), p3.GetHashCode()); + } + + [Fact] + public static void EqualityTest_NotCords() + { + Cords Cords = new(0, 0); + Assert.False(Cords.Equals(null)); + Assert.False(Cords.Equals(0)); + Assert.False(Cords.Equals(new PointF(0, 0))); + } + + [Fact] + public static void GetHashCodeTest() + { + Cords Cords = new(10, 10); + Assert.Equal(Cords.GetHashCode(), new Cords(10, 10).GetHashCode()); + Assert.NotEqual(Cords.GetHashCode(), new Cords(20, 10).GetHashCode()); + Assert.NotEqual(Cords.GetHashCode(), new Cords(10, 20).GetHashCode()); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(1, -2, 3, -4)] + public void ConversionTest(int x, int y, int width, int height) + { + Area rect = new(x, y, width, height); + RectangleF rectF = rect.Rectangle; + Assert.Equal(x, rectF.X); + Assert.Equal(y, rectF.Y); + Assert.Equal(width, rectF.Width); + Assert.Equal(height, rectF.Height); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(5, -5)] + public void ToStringTest(int x, int y) + { + Cords p = new(x, y); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "{{X={0},Y={1}}}", p.X, p.Y), p.ToString()); + } + } +} diff --git a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj index d93617f..c15a6ea 100644 --- a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj +++ b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj @@ -1,7 +1,7 @@  - True + False True Enable @@ -11,7 +11,7 @@ $(AssemblyName).Standard netstandard1.3;netstandard2.0;netstandard2.1;net6.0 - $(TargetFrameworks);net2.0-client + $(TargetFrameworks);net2.0-client;net4.5 diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs index 4649efe..88feffa 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs @@ -80,10 +80,10 @@ public async Task DumpScreenStringAsync(CancellationToken cancellationTo /// /// Clicks on the specified coordinates asynchronously. /// - /// The to click. + /// The to click. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public async Task ClickAsync(Point cords, CancellationToken cancellationToken = default) + public async Task ClickAsync(Cords cords, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input tap {cords.X} {cords.Y}", receiver, cancellationToken).ConfigureAwait(false); @@ -157,7 +157,7 @@ public async Task SwipeAsync(Element first, Element second, long speed, Cancella /// The time spent in swiping. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public async Task SwipeAsync(Point first, Point second, long speed, CancellationToken cancellationToken = default) + public async Task SwipeAsync(Cords first, Cords second, long speed, CancellationToken cancellationToken = default) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; await AdbClient.ExecuteShellCommandAsync(Device, $"input swipe {first.X} {first.Y} {second.X} {second.Y} {speed}", receiver, cancellationToken).ConfigureAwait(false); @@ -354,7 +354,7 @@ static IEnumerable FindElements(IAdbClient client, DeviceData device, X throw new ShellCommandUnresponsiveException(e); } } - return Enumerable.Empty(); + return []; } #if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs index a9327dd..b3aa12e 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs @@ -106,8 +106,8 @@ public string DumpScreenString() /// /// Clicks on the specified coordinates. /// - /// The to click. - public void Click(Point cords) + /// The to click. + public void Click(Cords cords) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input tap {cords.X} {cords.Y}", receiver); @@ -172,10 +172,10 @@ public void Swipe(Element first, Element second, long speed) /// /// Generates a swipe gesture from first coordinates to second coordinates. Specify the speed in ms. /// - /// The start . - /// The end . + /// The start . + /// The end . /// The time spent in swiping. - public void Swipe(Point first, Point second, long speed) + public void Swipe(Cords first, Cords second, long speed) { ConsoleOutputReceiver receiver = new() { ParsesErrors = false }; AdbClient.ExecuteShellCommand(Device, $"input swipe {first.X} {first.Y} {second.X} {second.Y} {speed}", receiver); diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs index 8e7afe9..83ce456 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs @@ -66,10 +66,10 @@ public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData d /// /// The to use when executing the command. /// The device on which to run the command. - /// The to click. + /// The to click. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public static Task ClickAsync(this IAdbClient client, DeviceData device, Point cords, CancellationToken cancellationToken = default) => + public static Task ClickAsync(this IAdbClient client, DeviceData device, Cords cords, CancellationToken cancellationToken = default) => new DeviceClient(client, device).ClickAsync(cords, cancellationToken); /// @@ -82,7 +82,7 @@ public static Task ClickAsync(this IAdbClient client, DeviceData device, Point c /// The time spent in swiping. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. - public static Task SwipeAsync(this IAdbClient client, DeviceData device, Point first, Point second, long speed, CancellationToken cancellationToken = default) => + public static Task SwipeAsync(this IAdbClient client, DeviceData device, Cords first, Cords second, long speed, CancellationToken cancellationToken = default) => new DeviceClient(client, device).SwipeAsync(first, second, speed, cancellationToken); /// diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs index 1f2398d..94fcffa 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs @@ -60,8 +60,8 @@ public static void ExecuteShellCommand(this IAdbClient client, DeviceData device /// /// An instance of a class that implements the interface. /// The device on which to clear the input text. - /// The to click. - public static void Click(this IAdbClient client, DeviceData device, Point cords) => + /// The to click. + public static void Click(this IAdbClient client, DeviceData device, Cords cords) => new DeviceClient(client, device).Click(cords); /// @@ -69,10 +69,10 @@ public static void Click(this IAdbClient client, DeviceData device, Point cords) /// /// An instance of a class that implements the interface. /// The device on which to clear the input text. - /// The start . - /// The end . + /// The start . + /// The end . /// The time spent in swiping. - public static void Swipe(this IAdbClient client, DeviceData device, Point first, Point second, long speed) => + public static void Swipe(this IAdbClient client, DeviceData device, Cords first, Cords second, long speed) => new DeviceClient(client, device).Swipe(first, second, speed); /// diff --git a/AdvancedSharpAdbClient/DeviceCommands/Models/Area.cs b/AdvancedSharpAdbClient/DeviceCommands/Models/Area.cs new file mode 100644 index 0000000..7444a20 --- /dev/null +++ b/AdvancedSharpAdbClient/DeviceCommands/Models/Area.cs @@ -0,0 +1,331 @@ +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace AdvancedSharpAdbClient.DeviceCommands.Models +{ + /// + /// Stores the location and size of a rectangular region. + /// + /// This is a host of type . + /// Using to get the value. + public struct Area : IEquatable, IEquatable + { + /// + /// Represents a structure with its properties left uninitialized. + /// + public static readonly Area Empty; + + /// + /// The that represents the location and size of this . + /// + internal Rectangle rectangle; + + /// + /// Initializes a new instance of the struct. + /// + public Area() : this(new Rectangle()) { } + + /// + /// Initializes a new instance of the struct. + /// + /// A that specifies the location and size for the new . +#if HAS_DRAWING + public +#else + internal +#endif + Area(Rectangle rectangle) : this(in rectangle) { } + + /// + /// Initializes a new instance of the struct. + /// + /// A that specifies the location and size for the new . + internal Area(in Rectangle rectangle) => this.rectangle = rectangle; + + /// + /// Initializes a new instance of the struct with the specified location and size. + /// + /// The x-coordinate of the upper-left corner of the rectangle. + /// The y-coordinate of the upper-left corner of the rectangle. + /// The width of the rectangle. + /// The height of the rectangle. + public Area(int x, int y, int width, int height) => rectangle = new Rectangle(x, y, width, height); + + /// + /// Creates a new with the specified location and size. + /// + /// The x-coordinate of the upper-left corner of this structure. + /// The y-coordinate of the upper-left corner of this structure. + /// The x-coordinate of the lower-right corner of this structure. + /// The y-coordinate of the lower-right corner of this structure. + /// The new that this method creates. + public static Area FromLTRB(int left, int top, int right, int bottom) => new(Rectangle.FromLTRB(left, top, right, bottom)); + + /// + /// Gets or sets the that represents the location and size of this . + /// +#if HAS_DRAWING + public +#else + internal +#endif + Rectangle Rectangle + { + readonly get => rectangle; + set => rectangle = value; + } + + /// + /// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this + /// . + /// + public Cords Location + { + readonly get => new(rectangle.Location); + set => rectangle.Location = value.Point; + } + + /// + /// Gets or sets the x-coordinate of the upper-left corner of the rectangular region defined by this + /// . + /// + public int X + { + readonly get => rectangle.X; + set => rectangle.X = value; + } + + /// + /// Gets or sets the y-coordinate of the upper-left corner of the rectangular region defined by this + /// . + /// + public int Y + { + readonly get => rectangle.Y; + set => rectangle.Y = value; + } + + /// + /// Gets or sets the width of the rectangular region defined by this . + /// + public int Width + { + readonly get => rectangle.Width; + set => rectangle.Width = value; + } + + /// + /// Gets or sets the width of the rectangular region defined by this . + /// + public int Height + { + readonly get => rectangle.Height; + set => rectangle.Height = value; + } + + /// + /// Gets the x-coordinate of the upper-left corner of the rectangular region defined by this + /// . + /// + public readonly int Left => rectangle.Left; + + /// + /// Gets the y-coordinate of the upper-left corner of the rectangular region defined by this + /// . + /// + public readonly int Top => rectangle.Top; + + /// + /// Gets the x-coordinate of the lower-right corner of the rectangular region defined by this + /// . + /// + public readonly int Right => rectangle.Right; + + /// + /// Gets the y-coordinate of the lower-right corner of the rectangular region defined by this + /// . + /// + public readonly int Bottom => rectangle.Bottom; + + /// + /// Tests whether this has a + /// or a of 0. + /// + public readonly bool IsEmpty => rectangle.IsEmpty; + + /// + /// Tests whether is a with the same location + /// and size of this Rectangle. + /// + /// The to test. + /// This method returns if is a structure + /// and its , , , and properties are equal to + /// the corresponding properties of this structure; otherwise, . + public override readonly bool Equals([NotNullWhen(true)] object? obj) => (obj is Area area && Equals(area)) || (obj is Rectangle rectangle && rectangle.Equals(rectangle)); + + /// + public readonly bool Equals(Area other) => rectangle.Equals(other.rectangle); + + /// +#if HAS_DRAWING + public +#else + internal +#endif + readonly bool Equals(Rectangle other) => rectangle.Equals(other); + + /// + /// Tests whether two objects have equal location and size. + /// + /// The structure that is to the left of the equality operator. + /// The structure that is to the right of the equality operator. + /// This operator returns if the two structures have equal + /// , , , and properties. + public static bool operator ==(Area left, Area right) => left.rectangle == right.rectangle; + + /// + /// Tests whether two objects differ in location or size. + /// + /// The structure that is to the left of the inequality operator. + /// The structure that is to the right of the inequality operator. + /// This operator returns if any of the , , + /// properties of the two structures are unequal; otherwise . + public static bool operator !=(Area left, Area right) => left.rectangle != right.rectangle; + + /// + /// Determines if the specified point is contained within the rectangular region defined by this + /// . + /// + /// The x-coordinate of the point to test. + /// The y-coordinate of the point to test. + /// This method returns if the point defined by and + /// is contained within this structure; otherwise . + public readonly bool Contains(int x, int y) => rectangle.Contains(x, y); + + /// + /// Determines if the specified point is contained within the rectangular region defined by this + /// . + /// + /// The to test. + /// This method returns if the point represented by + /// is contained within this structure; otherwise . + public readonly bool Contains(Cords pt) => rectangle.Contains(pt.Point); + + /// + /// Determines if the rectangular region represented by is entirely contained within the + /// rectangular region represented by this . + /// + /// The to test. + /// This method returns if the rectangular region represented by + /// is entirely contained within this structure; otherwise . + public readonly bool Contains(Area rect) => rectangle.Contains(rect.rectangle); + + /// + /// Returns the hash code for this structure. + /// + /// An integer that represents the hash code for this rectangle. + public override readonly int GetHashCode() => HashCode.Combine(rectangle); + + /// + /// Inflates this by the specified amount. + /// + /// The amount to inflate this horizontally. + /// The amount to inflate this vertically. + public void Inflate(int width, int height) => rectangle.Inflate(width, height); + + /// + /// Creates a that is inflated by the specified amount. + /// + /// The with which to start. This rectangle is not modified. + /// The amount to inflate this horizontally. + /// The amount to inflate this vertically. + public static Area Inflate(Area rect, int x, int y) + { + Area r = rect; + r.Inflate(x, y); + return r; + } + + /// + /// Creates a Rectangle that represents the intersection between this Rectangle and rect. + /// + /// The with which to intersect. + public void Intersect(Area rect) => rectangle.Intersect(rect.rectangle); + + /// + /// Creates a rectangle that represents the intersection between a and b. If there is no intersection, an + /// empty rectangle is returned. + /// + /// A rectangle to intersect. + /// A rectangle to intersect. + /// A that represents the intersection of and . + public static Area Intersect(Area a, Area b) + { + Rectangle result = Rectangle.Intersect(a.rectangle, b.rectangle); + return new Area(result); + } + + /// + /// Determines if this rectangle intersects with rect. + /// + /// The rectangle to test. + /// This method returns if there is any intersection, otherwise . + public readonly bool IntersectsWith(Area rect) => rectangle.IntersectsWith(rect.rectangle); + + /// + /// Creates a rectangle that represents the union between a and b. + /// + /// A rectangle to union. + /// A rectangle to union. + /// A structure that bounds the union of the two structures. + public static Area Union(Area a, Area b) + { + Rectangle result = Rectangle.Union(a.rectangle, b.rectangle); + return new Area(result); + } + + /// + /// Adjusts the location of this rectangle by the specified amount. + /// + /// Amount to offset the location. + public void Offset(Cords pos) => rectangle.Offset(pos.Point); + + /// + /// Adjusts the location of this rectangle by the specified amount. + /// + /// The horizontal offset. + /// The vertical offset. + public void Offset(int x, int y) => rectangle.Offset(x, y); + +#if HAS_DRAWING + /// + /// Creates a with the specified . + /// + /// The to convert. + /// The that results from the conversion. + public static implicit operator Rectangle(Area rect) => rect.rectangle; + + /// + /// Creates a with the specified . + /// + /// The to convert. + /// The that results from the conversion. + public static implicit operator Area(Rectangle rect) => new(in rect); +#else + /// + readonly bool IEquatable.Equals(Rectangle other) => Equals(other); +#endif + + /// + /// Converts the attributes of this to a human readable string. + /// + /// A string that contains the position, width, and height of this structure ¾ + /// for example, {X=20, Y=20, Width=100, Height=50}. + public override readonly string ToString() => rectangle.ToString(); + } +} diff --git a/AdvancedSharpAdbClient/DeviceCommands/Models/Cords.cs b/AdvancedSharpAdbClient/DeviceCommands/Models/Cords.cs new file mode 100644 index 0000000..2c83b39 --- /dev/null +++ b/AdvancedSharpAdbClient/DeviceCommands/Models/Cords.cs @@ -0,0 +1,215 @@ +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; + +namespace AdvancedSharpAdbClient.DeviceCommands.Models +{ + /// + /// Represents an ordered pair of integer x- and y-coordinates that defines a point in a two-dimensional plane. + /// + /// This is a host of type . + /// Using to get the value. + public struct Cords : IEquatable, IEquatable + { + /// + /// Creates a new instance of the struct with member data left uninitialized. + /// + public static readonly Cords Empty; + + /// + /// The that represents the coordinates of this . + /// + private Point point; + + /// + /// Initializes a new instance of the struct. + /// + public Cords() : this(new Point()) { } + + /// + /// Initializes a new instance of the struct. + /// + /// A that specifies the coordinates for the new . +#if HAS_DRAWING + public +#else + internal +#endif + Cords(Point point) : this(in point) { } + + /// + /// Initializes a new instance of the struct. + /// + /// A that specifies the coordinates for the new . + internal Cords(in Point point) => this.point = point; + + /// + /// Initializes a new instance of the struct with the specified coordinates. + /// + /// The horizontal "X" coordinate. + /// The vertical "Y" coordinate. + public Cords(int x, int y) : this(new Point(x, y)) { } + + /// + /// Initializes a new instance of the Point class using coordinates specified by an integer value. + /// + public Cords(int dw) : this(new Point(dw)) { } + + /// + /// Gets a value indicating whether this is empty. + /// + public readonly bool IsEmpty => point.IsEmpty; + + /// + /// Gets or sets the that represents the coordinates of this . + /// +#if HAS_DRAWING + public +#else + internal +#endif + Point Point + { + readonly get => point; + set => point = value; + } + + /// + /// Gets the x-coordinate of this . + /// + public int X + { + readonly get => point.X; + set => point.X = value; + } + + /// + /// Gets the y-coordinate of this . + /// + public int Y + { + readonly get => point.Y; + set => point.Y = value; + } + + /// + /// Compares two objects. The result specifies whether the values of the + /// and properties of the two + /// objects are equal. + /// + /// A to compare. + /// A to compare. + /// if the and values + /// of and are equal; otherwise, . + public static bool operator ==(Cords left, Cords right) => left.point == right.point; + + /// + /// Compares two objects. The result specifies whether the values of the + /// or properties of the two + /// objects are unequal. + /// + /// A to compare. + /// A to compare. + /// if the values of either the or values + /// of and differ; otherwise, . + public static bool operator !=(Cords left, Cords right) => left.point != right.point; + + /// + /// Specifies whether this contains the same coordinates as the specified + /// . + /// + /// The to test for equality. + /// if is a and has the same coordinates as this point instance. + public override readonly bool Equals([NotNullWhen(true)] object? obj) => (obj is Cords cords && Equals(cords)) || (obj is Point point && this.point.Equals(point)); + + /// + /// Specifies whether this contains the same coordinates as the specified + /// . + /// + /// The point to test for equality. + /// if has the same coordinates as this point instance. + public readonly bool Equals(Cords other) => point.Equals(other.point); + + /// + /// Specifies whether this contains the same coordinates as the specified + /// . + /// + /// The point to test for equality. + /// if has the same coordinates as this point instance. +#if HAS_DRAWING + public +#else + internal +#endif + readonly bool Equals(Point other) => point.Equals(other); + + /// + /// Returns a hash code. + /// + /// An integer value that specifies a hash value for this . + public override readonly int GetHashCode() => HashCode.Combine(point); + + /// + /// Translates this by the specified amount. + /// + /// The amount to offset the x-coordinate. + /// The amount to offset the y-coordinate. + public void Offset(int dx, int dy) => point.Offset(dx, dy); + +#if HAS_DRAWING + /// + /// Creates a with the coordinates of the specified . + /// + /// The to convert. + /// The that results from the conversion. + public static implicit operator Point(Cords p) => p.point; + + /// + /// Creates a with the coordinates of the specified . + /// + /// The to convert. + /// The that results from the conversion. + public static implicit operator Cords(Point p) => new(in p); +#else + /// + /// Specifies whether this contains the same coordinates as the specified + /// . + /// + /// The point to test for equality. + /// if has the same coordinates as this point instance. + readonly bool IEquatable.Equals(Point other) => Equals(other); +#endif + + /// + /// Translates this by the specified amount. + /// + /// The used offset this . +#if HAS_DRAWING + public +#else + internal +#endif + void Offset(Point p) => point.Offset(p); + + /// + /// Deconstruct the class. + /// + /// The horizontal "X" coordinate. + /// The vertical "Y" coordinate. + public readonly void Deconstruct(out int cx, out int cy) + { + cx = X; + cy = Y; + } + + /// + /// Converts this to a human readable string. + /// + /// A string that represents this . + public override readonly string ToString() => point.ToString(); + } +} diff --git a/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs b/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs index e9c8fd4..b874879 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs @@ -26,13 +26,13 @@ public class Element : IEquatable /// /// The current ADB client that manages the connection. /// The current device containing the element. - /// The coordinates and size of the element. + /// The coordinates and size of the element. /// Gets or sets element attributes. - public Element(IAdbClient client, DeviceData device, Rectangle rectangle, Dictionary? attributes = null) + public Element(IAdbClient client, DeviceData device, Area area, Dictionary? attributes = null) { Client = client; Device = device; - Bounds = rectangle; + Bounds = area; Attributes = attributes; } @@ -53,7 +53,7 @@ public Element(IAdbClient client, DeviceData device, XmlNode? xmlNode) if (xmlNode.Attributes["bounds"]?.Value is string bounds) { string[] cords = bounds.Split(separator, StringSplitOptions.RemoveEmptyEntries); // x1, y1, x2, y2 - Bounds = Rectangle.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); + Bounds = Area.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); } Attributes = new(xmlNode.Attributes.Count); @@ -103,7 +103,7 @@ public Element(IAdbClient client, DeviceData device, Windows.Data.Xml.Dom.IXmlNo if (xmlNode.Attributes.GetNamedItem("bounds")?.NodeValue?.ToString() is string bounds) { string[] cords = bounds.Split(separator, StringSplitOptions.RemoveEmptyEntries); // x1, y1, x2, y2 - Bounds = Rectangle.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); + Bounds = Area.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); } Attributes = new(xmlNode.Attributes.Count); @@ -145,7 +145,7 @@ static IEnumerable FindElements(IAdbClient client, DeviceData device, W /// /// Gets the coordinates and size of the element. /// - public Rectangle Bounds { get; init; } + public Area Bounds { get; init; } /// /// Gets the children of this element. @@ -165,7 +165,7 @@ static IEnumerable FindElements(IAdbClient client, DeviceData device, W /// /// Gets the coordinates of the the center of the element. /// - public Point Center => unchecked(new(Bounds.X + (Bounds.Width / 2), Bounds.Y + (Bounds.Height / 2))); + public Cords Center => unchecked(new(Bounds.X + (Bounds.Width / 2), Bounds.Y + (Bounds.Height / 2))); /// /// Gets the text of the element. diff --git a/AdvancedSharpAdbClient/Models/Framebuffer.cs b/AdvancedSharpAdbClient/Models/Framebuffer.cs index d84cca0..f16e201 100644 --- a/AdvancedSharpAdbClient/Models/Framebuffer.cs +++ b/AdvancedSharpAdbClient/Models/Framebuffer.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Drawing; using System.Net; using System.Threading; diff --git a/AdvancedSharpAdbClient/Models/FramebufferHeader.cs b/AdvancedSharpAdbClient/Models/FramebufferHeader.cs index 2a1e49b..800d20b 100644 --- a/AdvancedSharpAdbClient/Models/FramebufferHeader.cs +++ b/AdvancedSharpAdbClient/Models/FramebufferHeader.cs @@ -5,6 +5,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Drawing; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/AdvancedSharpAdbClient/Polyfills/Point.cs b/AdvancedSharpAdbClient/Polyfills/Point.cs index 7e71028..d41a541 100644 --- a/AdvancedSharpAdbClient/Polyfills/Point.cs +++ b/AdvancedSharpAdbClient/Polyfills/Point.cs @@ -2,20 +2,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -namespace AdvancedSharpAdbClient.Polyfills +namespace System.Drawing { /// /// Represents an ordered pair of x and y coordinates that define a point in a two-dimensional plane. /// [EditorBrowsable(EditorBrowsableState.Never)] - public struct Point : IEquatable + internal struct Point : IEquatable { /// - /// Creates a new instance of the class with member data left uninitialized. + /// Creates a new instance of the struct with member data left uninitialized. /// public static readonly Point Empty; @@ -151,4 +150,6 @@ public readonly void Deconstruct(out int cx, out int cy) private static short LowInt16(int n) => unchecked((short)(n & 0xffff)); } } +#else +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.Point))] #endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Polyfills/Rectangle.cs b/AdvancedSharpAdbClient/Polyfills/Rectangle.cs index e721c71..c18978c 100644 --- a/AdvancedSharpAdbClient/Polyfills/Rectangle.cs +++ b/AdvancedSharpAdbClient/Polyfills/Rectangle.cs @@ -2,11 +2,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -namespace AdvancedSharpAdbClient.Polyfills +namespace System.Drawing { /// /// Stores the location and size of a rectangular region. @@ -16,7 +15,7 @@ namespace AdvancedSharpAdbClient.Polyfills /// The width of the rectangle. /// The height of the rectangle. [EditorBrowsable(EditorBrowsableState.Never)] - public struct Rectangle(int x, int y, int width, int height) : IEquatable + internal struct Rectangle(int x, int y, int width, int height) : IEquatable { /// /// Represents a structure with its properties left uninitialized. @@ -282,4 +281,6 @@ public void Offset(int x, int y) public override readonly string ToString() => $"{{X={X},Y={Y},Width={Width},Height={Height}}}"; } } +#else +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Drawing.Rectangle))] #endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Properties/GlobalUsings.cs b/AdvancedSharpAdbClient/Properties/GlobalUsings.cs index 0b06441..2a32ccd 100644 --- a/AdvancedSharpAdbClient/Properties/GlobalUsings.cs +++ b/AdvancedSharpAdbClient/Properties/GlobalUsings.cs @@ -29,12 +29,8 @@ global using Windows.UI.Xaml.Media.Imaging; global using Buffer = System.Buffer; global using DateTime = System.DateTime; -global using TimeSpan = System.TimeSpan; -#if HAS_DRAWING global using Point = System.Drawing.Point; -#else -global using Point = AdvancedSharpAdbClient.Polyfills.Point; -#endif +global using TimeSpan = System.TimeSpan; #endif #if WINDOWS10_0_17763_0_OR_GREATER @@ -55,10 +51,6 @@ global using System.Buffers; #endif -#if HAS_DRAWING -global using System.Drawing; -#endif - #if HAS_IMAGING global using System.Drawing.Imaging; #endif From edd046ad176d3edd76ecf0d50a050df5c7f37eee Mon Sep 17 00:00:00 2001 From: wherewhere Date: Tue, 13 Feb 2024 17:37:33 +0800 Subject: [PATCH 6/6] DeviceClient change to record Add equal operator --- .../DeviceCommands/DeviceClientTexts.cs | 74 +++++++++++++++++++ .../DeviceCommands/Models/ElementTests.cs | 65 ++++++++++++++++ .../Models/DeviceDataTests.cs | 23 ++++++ AdvancedSharpAdbClient/AdbClient.cs | 2 +- .../AdbCommandLineClient.cs | 8 +- .../DeviceCommands/DeviceClient.Async.cs | 2 +- .../DeviceCommands/DeviceClient.cs | 56 ++++++++------ .../DeviceCommands/Models/Element.cs | 56 +++++++++----- .../Receivers/PackageManagerReceiver.cs | 1 - AdvancedSharpAdbClient/DeviceMonitor.cs | 2 +- .../Extensions/AdbClientExtensions.cs | 8 ++ AdvancedSharpAdbClient/Models/AdbResponse.cs | 8 +- AdvancedSharpAdbClient/Models/DeviceData.cs | 41 +++++++++- AdvancedSharpAdbClient/Models/ForwardData.cs | 21 +++++- AdvancedSharpAdbClient/Models/ForwardSpec.cs | 8 +- .../Properties/GlobalUsings.cs | 1 + 16 files changed, 319 insertions(+), 57 deletions(-) create mode 100644 AdvancedSharpAdbClient.Tests/DeviceCommands/Models/ElementTests.cs diff --git a/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs b/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs index 32968a0..9cb5253 100644 --- a/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs +++ b/AdvancedSharpAdbClient.Tests/DeviceCommands/DeviceClientTexts.cs @@ -16,6 +16,9 @@ public partial class DeviceClientTexts State = DeviceState.Online }; + /// + /// Tests the method. + /// [Fact] public void ConstructorNullTest() { @@ -25,6 +28,77 @@ public void ConstructorNullTest() _ = Assert.Throws(() => new DeviceClient(Substitute.For(), new DeviceData())); } + /// + /// Tests the method. + /// + [Fact] + public void DeconstructTest() + { + IAdbClient client = Substitute.For(); + DeviceClient deviceClient = new(client, Device); + (IAdbClient adbClient, DeviceData device) = deviceClient; + Assert.Equal(client, adbClient); + Assert.Equal(Device, device); + } + + /// + /// Tests the method. + /// + [Fact] + public void EqualityTest() + { + IAdbClient c1 = Substitute.For(); + IAdbClient c2 = Substitute.For(); + DeviceData d1 = new() { Serial = "1" }; + DeviceData d2 = new() { Serial = "2" }; + + DeviceClient p1 = new(c1, d1); + DeviceClient p2 = new(c2, d2); + DeviceClient p3 = new(c1, d1); + + Assert.True(p1 == p3); + Assert.True(p1 != p2); + Assert.True(p2 != p3); + + Assert.True(p1.Equals(p3)); + Assert.False(p1.Equals(p2)); + Assert.False(p2.Equals(p3)); + + Assert.True(p1.Equals((object)p3)); + Assert.False(p1.Equals((object)p2)); + Assert.False(p2.Equals((object)p3)); + + Assert.Equal(p1.GetHashCode(), p3.GetHashCode()); + } + + /// + /// Tests the method. + /// + [Fact] + public void CloneTest() + { + IAdbClient client = Substitute.For(); + IAdbClient newClient = Substitute.For(); + DeviceData device = new() { Serial = "1" }; + DeviceData newDevice = new() { Serial = "2" }; + + DeviceClient deviceClient = new(client, device); + Assert.Equal(client, deviceClient.AdbClient); + Assert.Equal(device, deviceClient.Device); + + deviceClient = deviceClient with { }; + Assert.Equal(client, deviceClient.AdbClient); + Assert.Equal(device, deviceClient.Device); + + deviceClient = deviceClient with { AdbClient = newClient }; + Assert.Equal(newClient, deviceClient.AdbClient); + Assert.Equal(device, deviceClient.Device); + + deviceClient = deviceClient with { Device = newDevice }; + Assert.Equal(newClient, deviceClient.AdbClient); + Assert.Equal(newDevice, deviceClient.Device); + } + /// /// Tests the method. /// diff --git a/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/ElementTests.cs b/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/ElementTests.cs new file mode 100644 index 0000000..5a2d250 --- /dev/null +++ b/AdvancedSharpAdbClient.Tests/DeviceCommands/Models/ElementTests.cs @@ -0,0 +1,65 @@ +using NSubstitute; +using System; +using System.Linq; +using System.Xml; +using Xunit; + +namespace AdvancedSharpAdbClient.DeviceCommands.Models.Tests +{ + /// + /// Tests the class. + /// + public class ElementTests + { + public ElementTests() + { + XmlDocument doc = new(); + doc.Load(@"Assets/DumpScreen.Clean.xml"); + XmlNode = doc.SelectSingleNode("hierarchy/node"); + } + + private XmlNode XmlNode { get; init; } + + [Fact] + public void PropertiesTest() + { + IAdbClient client = Substitute.For(); + DeviceData device = new(); + + Element element = Element.FromXmlNode(client, device, XmlNode); + Assert.Equal(client, element.Client); + Assert.Equal(device, element.Device); + Assert.Equal("android.widget.FrameLayout", element.Class); + Assert.Equal("com.bilibili.app.in", element.Package); + Assert.Equal(Area.FromLTRB(0, 0, 1440, 3060), element.Bounds); + Assert.Equal(144, element.GetChildCount()); + + Element child = element[0][0][0][0][0][0][0][0][2][1][0][0]; + Assert.Equal(client, child.Client); + Assert.Equal(device, child.Device); + Assert.Equal("where-where", child.Text); + Assert.Equal("android.widget.TextView", child.Class); + Assert.Equal("com.bilibili.app.in", child.Package); + Assert.Equal("com.bilibili.app.in:id/header_info_name", child.ResourceID); + Assert.Equal(Area.FromLTRB(45, 889, 427, 973), child.Bounds); + Assert.Equal(child, element.FindDescendantOrSelf(x => x.Text == "where-where")); + Assert.Equal(2, element.FindDescendants().Where(x => x.Text == "where-where").Count()); + } + + [Fact] + public void EqualityTest() + { + IAdbClient client = Substitute.For(); + DeviceData device = new(); + + Element e1 = Element.FromXmlNode(client, device, XmlNode); + Element e2 = Element.FromXmlNode(client, device, XmlNode); + + Assert.True(e1 == e2); + Assert.True(e1.Equals(e2)); + Assert.True(e1.Equals((object)e2)); + Assert.Equal(e1.GetHashCode(), e2.GetHashCode()); + Assert.Equal(e1.FindDescendants(), e2.FindDescendants()); + } + } +} diff --git a/AdvancedSharpAdbClient.Tests/Models/DeviceDataTests.cs b/AdvancedSharpAdbClient.Tests/Models/DeviceDataTests.cs index cf001fa..4b8d2ef 100644 --- a/AdvancedSharpAdbClient.Tests/Models/DeviceDataTests.cs +++ b/AdvancedSharpAdbClient.Tests/Models/DeviceDataTests.cs @@ -205,5 +205,28 @@ public void CreateFromDeviceDataConnectingTest() Assert.Equal(DeviceState.Unknown, device.State); Assert.Equal(string.Empty, device.Usb); } + + [Theory] + [InlineData("R32D102SZAE device transport_id:6", "R32D102SZAE", "", "", "", "6")] + [InlineData("emulator-5554 device product:sdk_google_phone_x86 model:Android_SDK_built_for_x86 device:generic_x86 transport_id:1", "emulator-5554", "sdk_google_phone_x86", "Android_SDK_built_for_x86", "generic_x86", "1")] + [InlineData("00bc13bcf4bacc62 device product:bullhead model:Nexus_5X device:bullhead transport_id:1", "00bc13bcf4bacc62", "bullhead", "Nexus_5X", "bullhead", "1")] + public void EqualityTest(string data, string serial, string product, string model, string name, string transportId) + { + DeviceData d1 = DeviceData.CreateFromAdbData(data); + DeviceData d2 = new() + { + Serial = serial, + Product = product, + Model = model, + Name = name, + TransportId = transportId, + State = DeviceState.Online + }; + + Assert.True(d1 == d2); + + Assert.True(d1.Equals(d2)); + Assert.Equal(d1.GetHashCode(), d2.GetHashCode()); + } } } diff --git a/AdvancedSharpAdbClient/AdbClient.cs b/AdvancedSharpAdbClient/AdbClient.cs index 8844313..e71bb6c 100644 --- a/AdvancedSharpAdbClient/AdbClient.cs +++ b/AdvancedSharpAdbClient/AdbClient.cs @@ -1133,7 +1133,7 @@ public IEnumerable GetFeatureSet(DeviceData device) protected static void EnsureDevice([NotNull] DeviceData? device) { ExceptionExtensions.ThrowIfNull(device); - if (string.IsNullOrEmpty(device.Serial)) + if (device.IsEmpty) { throw new ArgumentOutOfRangeException(nameof(device), "You must specific a serial number for the device"); } diff --git a/AdvancedSharpAdbClient/AdbCommandLineClient.cs b/AdvancedSharpAdbClient/AdbCommandLineClient.cs index d158716..f08c851 100644 --- a/AdvancedSharpAdbClient/AdbCommandLineClient.cs +++ b/AdvancedSharpAdbClient/AdbCommandLineClient.cs @@ -110,8 +110,12 @@ public virtual List ExecuteAdbCommand(string command) string error = StringExtensions.Join(Environment.NewLine, errorOutput!); throw new AdbException($"The adb process returned error code {status} when running command {command} with error output:{Environment.NewLine}{error}", error); } - else if (status != 0) { throw new AdbException($"The adb process returned error code {status} when running command {command}"); } - else { return standardOutput; } + else + { + return status != 0 + ? throw new AdbException($"The adb process returned error code {status} when running command {command}") + : standardOutput; + } } /// diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs index 88feffa..87c6b8d 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.Async.cs @@ -13,7 +13,7 @@ namespace AdvancedSharpAdbClient.DeviceCommands { - public partial class DeviceClient + public partial record class DeviceClient { /// /// Gets the current device screen snapshot asynchronously. diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs index b3aa12e..f0f6cd3 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceClient.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -15,34 +16,19 @@ namespace AdvancedSharpAdbClient.DeviceCommands /// /// A class which contains methods for interacting with an Android device by /// - public partial class DeviceClient + /// The to use to communicate with the Android Debug Bridge. + /// The device on which to process command. + public partial record class DeviceClient(IAdbClient AdbClient, DeviceData Device) { /// - /// Initializes a new instance of the class. + /// Gets the to use when communicating with the device. /// - /// The to use to communicate with the Android Debug Bridge. - /// The device on which to process command. - public DeviceClient(IAdbClient client, DeviceData device) - { - ExceptionExtensions.ThrowIfNull(client); - ExceptionExtensions.ThrowIfNull(device); - if (string.IsNullOrEmpty(device.Serial)) - { - throw new ArgumentOutOfRangeException(nameof(device), "You must specific a serial number for the device"); - } - Device = device; - AdbClient = client; - } + public IAdbClient AdbClient { get; init; } = AdbClient ?? throw new ArgumentNullException(nameof(AdbClient)); /// /// Gets the device. /// - public DeviceData Device { get; init; } - - /// - /// Gets the to use when communicating with the device. - /// - public IAdbClient AdbClient { get; init; } + public DeviceData Device { get; init; } = EnsureDevice(Device); /// /// Gets the current device screen snapshot. @@ -415,6 +401,34 @@ public void Deconstruct(out IAdbClient client, out DeviceData device) device = Device; } + /// + /// Throws an if the + /// parameter is , and a + /// if does not have a valid serial number. + /// + /// A object to validate. + /// The parameter, if it is valid. + protected static DeviceData EnsureDevice([NotNull] DeviceData? device) + { + ExceptionExtensions.ThrowIfNull(device); + return device.IsEmpty + ? throw new ArgumentOutOfRangeException(nameof(device), "You must specific a serial number for the device") + : device; + } + +#if !NET40_OR_GREATER && !NETCOREAPP2_0_OR_GREATER && !NETSTANDARD2_0_OR_GREATER && !UAP10_0_15138_0 + /// + public override int GetHashCode() => HashCode.Combine(EqualityContract, AdbClient, Device); + + /// + public virtual bool Equals(DeviceClient? other) => + (object?)this == other || + (other != (object?)null + && EqualityComparer.Default.Equals(EqualityContract, other.EqualityContract) + && EqualityComparer.Default.Equals(AdbClient, other.AdbClient) + && EqualityComparer.Default.Equals(Device, other.Device)); +#endif + #if NET7_0_OR_GREATER [GeneratedRegex("<\\?xml(.?)*")] private static partial Regex GetXmlRegex(); diff --git a/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs b/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs index b874879..8c6bf6b 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/Models/Element.cs @@ -50,15 +50,16 @@ public Element(IAdbClient client, DeviceData device, XmlNode? xmlNode) if (xmlNode?.Attributes != null) { - if (xmlNode.Attributes["bounds"]?.Value is string bounds) - { - string[] cords = bounds.Split(separator, StringSplitOptions.RemoveEmptyEntries); // x1, y1, x2, y2 - Bounds = Area.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); - } - + bool foundBounds = false; Attributes = new(xmlNode.Attributes.Count); foreach (XmlAttribute at in xmlNode.Attributes.OfType()) { + if (!foundBounds && at.Name == "bounds" && at.Value is string bounds) + { + string[] cords = bounds.Split(separator, StringSplitOptions.RemoveEmptyEntries); // x1, y1, x2, y2 + Bounds = Area.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); + foundBounds = true; + } Attributes[at.Name] = at.Value; } } @@ -100,15 +101,16 @@ public Element(IAdbClient client, DeviceData device, Windows.Data.Xml.Dom.IXmlNo if (xmlNode.Attributes != null) { - if (xmlNode.Attributes.GetNamedItem("bounds")?.NodeValue?.ToString() is string bounds) - { - string[] cords = bounds.Split(separator, StringSplitOptions.RemoveEmptyEntries); // x1, y1, x2, y2 - Bounds = Area.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); - } - + bool foundBounds = false; Attributes = new(xmlNode.Attributes.Count); foreach (Windows.Data.Xml.Dom.IXmlNode at in xmlNode.Attributes) { + if (!foundBounds && at.NodeName == "bounds" && at.NodeValue is string bounds) + { + string[] cords = bounds.Split(separator, StringSplitOptions.RemoveEmptyEntries); // x1, y1, x2, y2 + Bounds = Area.FromLTRB(int.Parse(cords[0]), int.Parse(cords[1]), int.Parse(cords[2]), int.Parse(cords[3])); + foundBounds = true; + } Attributes[at.NodeName] = at.NodeValue.ToString(); } } @@ -416,18 +418,38 @@ public IEnumerable FindDescendants() /// An enumerator that can be used to iterate through the . public IEnumerator GetEnumerator() => FindDescendants().GetEnumerator(); + /// + /// Tests whether two objects are equally. + /// + /// The structure that is to the left of the equality operator. + /// The structure that is to the right of the equality operator. + /// This operator returns if the two structures are equally; otherwise . + public static bool operator ==(Element? left, Element? right) => (object?)left == right || (left?.Equals(right) ?? false); + + /// + /// Tests whether two objects are different. + /// + /// The structure that is to the left of the inequality operator. + /// The structure that is to the right of the inequality operator. + /// This operator returns if the two structures are unequally; otherwise . + public static bool operator !=(Element? left, Element? right) => !(left == right); + /// public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as Element); /// public bool Equals([NotNullWhen(true)] Element? other) => - other != null - && Client == other.Client - && Device == other.Device + (object?)this == other || + (other != (object?)null + && EqualityComparer.Default.Equals(Client, other.Client) + && EqualityComparer.Default.Equals(Device, other.Device) && (Node == null ? Bounds == other.Bounds - && Attributes == other.Attributes - : Node == other.Node); + && other.Attributes == null + ? Attributes == null + : Attributes?.SequenceEqual(other.Attributes!) == true + : other.Node != null + && Node.OuterXml == other.Node.OuterXml)); /// public override int GetHashCode() => diff --git a/AdvancedSharpAdbClient/DeviceCommands/Receivers/PackageManagerReceiver.cs b/AdvancedSharpAdbClient/DeviceCommands/Receivers/PackageManagerReceiver.cs index ab7f1aa..beff862 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/Receivers/PackageManagerReceiver.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/Receivers/PackageManagerReceiver.cs @@ -2,7 +2,6 @@ // Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. // -using System; using System.Collections.Generic; namespace AdvancedSharpAdbClient.DeviceCommands.Receivers diff --git a/AdvancedSharpAdbClient/DeviceMonitor.cs b/AdvancedSharpAdbClient/DeviceMonitor.cs index 4ac331c..df80a76 100644 --- a/AdvancedSharpAdbClient/DeviceMonitor.cs +++ b/AdvancedSharpAdbClient/DeviceMonitor.cs @@ -316,7 +316,7 @@ protected virtual void DeviceMonitorLoop() MonitorLoopFinished.Set(); } } - + /// /// Initializes the and sends the host:track-devices command to the adb server. /// diff --git a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs index 1b406e8..e2fec20 100644 --- a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs +++ b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs @@ -329,6 +329,14 @@ public static string Disconnect(this IAdbClient client, IPEndPoint endpoint) => public static string Disconnect(this IAdbClient client, string host) => client.Disconnect(host, AdbClient.DefaultPort); + /// + /// Creates a new instance of the class, which can be used to interact with a device. + /// + /// The instance to use to interact with the device. + /// The device to interact with. + /// A new instance of the class. + public static DeviceClient CreateDeviceClient(this IAdbClient client, DeviceData device) => new(client, device); + #if !NETFRAMEWORK || NET40_OR_GREATER /// /// Runs the event log service on a device. diff --git a/AdvancedSharpAdbClient/Models/AdbResponse.cs b/AdvancedSharpAdbClient/Models/AdbResponse.cs index 0f5dd35..43b5074 100644 --- a/AdvancedSharpAdbClient/Models/AdbResponse.cs +++ b/AdvancedSharpAdbClient/Models/AdbResponse.cs @@ -81,10 +81,10 @@ public void Throw() /// public bool Equals(AdbResponse other) => - other.IOSuccess == IOSuccess - && string.Equals(other.Message, Message, StringComparison.OrdinalIgnoreCase) - && other.Okay == Okay - && other.Timeout == Timeout; + IOSuccess == other.IOSuccess + && string.Equals(Message, other.Message, StringComparison.OrdinalIgnoreCase) + && Okay == other.Okay + && Timeout == other.Timeout; /// public override int GetHashCode() => HashCode.Combine(IOSuccess, Message, Okay, Timeout); diff --git a/AdvancedSharpAdbClient/Models/DeviceData.cs b/AdvancedSharpAdbClient/Models/DeviceData.cs index 39b74a2..72c8218 100644 --- a/AdvancedSharpAdbClient/Models/DeviceData.cs +++ b/AdvancedSharpAdbClient/Models/DeviceData.cs @@ -62,7 +62,7 @@ public DeviceData(string data) : this() /// /// Gets or sets the device state. /// - public DeviceState State { get; set; } + public DeviceState State { get; set; } = DeviceState.Unknown; /// /// Gets or sets the device model name. @@ -99,6 +99,11 @@ public DeviceData(string data) : this() /// public string Message { get; init; } = string.Empty; + /// + /// if does not have a valid serial number; otherwise, . + /// + public bool IsEmpty => string.IsNullOrEmpty(Serial); + /// /// Creates a new instance of the class based on /// data retrieved from the Android Debug Bridge. @@ -107,12 +112,42 @@ public DeviceData(string data) : this() /// A object that represents the device. public static DeviceData CreateFromAdbData(string data) => new(data); + /// + /// Creates a new instance of the class, which can be used to interact with this device. + /// + /// The instance to use to interact with the device. + /// A new instance of the class. + public DeviceClient CreateDeviceClient(IAdbClient client) => new(client, this); + + /// + /// Creates a new instance of the class, which can be used to interact with this device. + /// + /// A new instance of the class. + public DeviceClient CreateDeviceClient() => new(new AdbClient(), this); + + /// + /// Tests whether two objects are equally. + /// + /// The structure that is to the left of the equality operator. + /// The structure that is to the right of the equality operator. + /// This operator returns if the two structures are equally; otherwise . + public static bool operator ==(DeviceData? left, DeviceData? right) => (object?)left == right || (left?.Equals(right) ?? false); + + /// + /// Tests whether two objects are different. + /// + /// The structure that is to the left of the inequality operator. + /// The structure that is to the right of the inequality operator. + /// This operator returns if the two structures are unequally; otherwise . + public static bool operator !=(DeviceData? left, DeviceData? right) => !(left == right); + /// public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as DeviceData); /// public bool Equals([NotNullWhen(true)] DeviceData? other) => - other != null + (object?)this == other || + (other != (object?)null && Serial == other.Serial && State == other.State && Model == other.Model @@ -121,7 +156,7 @@ public bool Equals([NotNullWhen(true)] DeviceData? other) => && Features == other.Features && Usb == other.Usb && TransportId == other.TransportId - && Message == other.Message; + && Message == other.Message); /// public override int GetHashCode() diff --git a/AdvancedSharpAdbClient/Models/ForwardData.cs b/AdvancedSharpAdbClient/Models/ForwardData.cs index b5a6e51..3edf3aa 100644 --- a/AdvancedSharpAdbClient/Models/ForwardData.cs +++ b/AdvancedSharpAdbClient/Models/ForwardData.cs @@ -75,15 +75,32 @@ public ForwardData(string value) : this() [return: NotNullIfNotNull(nameof(value))] public static ForwardData? FromString(string? value) => value == null ? null : new ForwardData(value); + /// + /// Tests whether two objects are equally. + /// + /// The structure that is to the left of the equality operator. + /// The structure that is to the right of the equality operator. + /// This operator returns if the two structures are equally; otherwise . + public static bool operator ==(ForwardData? left, ForwardData? right) => (object?)left == right || (left?.Equals(right) ?? false); + + /// + /// Tests whether two objects are different. + /// + /// The structure that is to the left of the inequality operator. + /// The structure that is to the right of the inequality operator. + /// This operator returns if the two structures are unequally; otherwise . + public static bool operator !=(ForwardData? left, ForwardData? right) => !(left == right); + /// public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as ForwardData); /// public bool Equals([NotNullWhen(true)] ForwardData? other) => - other != null + (object?)this == other || + (other != (object?)null && SerialNumber == other.SerialNumber && Local == other.Local - && Remote == other.Remote; + && Remote == other.Remote); /// public override int GetHashCode() => HashCode.Combine(SerialNumber, Local, Remote); diff --git a/AdvancedSharpAdbClient/Models/ForwardSpec.cs b/AdvancedSharpAdbClient/Models/ForwardSpec.cs index ce3e83c..1abf41a 100644 --- a/AdvancedSharpAdbClient/Models/ForwardSpec.cs +++ b/AdvancedSharpAdbClient/Models/ForwardSpec.cs @@ -134,15 +134,12 @@ or ForwardProtocol.LocalReserved }; } - /// - public override int GetHashCode() => HashCode.Combine(Protocol, Port, ProcessId, SocketName); - /// public override bool Equals([NotNullWhen(true)] object? obj) => obj is ForwardSpec other && Equals(other); /// public bool Equals(ForwardSpec other) => - other.Protocol == Protocol + Protocol == other.Protocol && Protocol switch { ForwardProtocol.JavaDebugWireProtocol => ProcessId == other.ProcessId, @@ -154,6 +151,9 @@ or ForwardProtocol.LocalReserved _ => false, }; + /// + public override int GetHashCode() => HashCode.Combine(Protocol, Port, ProcessId, SocketName); + /// /// Tests whether two objects are equally. /// diff --git a/AdvancedSharpAdbClient/Properties/GlobalUsings.cs b/AdvancedSharpAdbClient/Properties/GlobalUsings.cs index 2a32ccd..ca851c2 100644 --- a/AdvancedSharpAdbClient/Properties/GlobalUsings.cs +++ b/AdvancedSharpAdbClient/Properties/GlobalUsings.cs @@ -1,4 +1,5 @@ #region AdvancedSharpAdbClient +global using AdvancedSharpAdbClient.DeviceCommands; global using AdvancedSharpAdbClient.DeviceCommands.Models; global using AdvancedSharpAdbClient.DeviceCommands.Receivers; global using AdvancedSharpAdbClient.Exceptions;