diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 72b1f16..df75ce3 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -30,7 +30,7 @@ jobs: fetch-depth: 0 - name: Setup .NET Core App - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: ${{ env.DOTNET_VERSION }} @@ -46,7 +46,7 @@ jobs: pack-and-publish: if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' needs: build-and-test - runs-on: windows-latest + runs-on: windows-2025-vs2026 env: Solution_Name: AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj @@ -57,7 +57,7 @@ jobs: fetch-depth: 0 - name: Setup .NET Core App - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: ${{ env.DOTNET_VERSION }} @@ -67,10 +67,10 @@ jobs: msbuild-architecture: x64 - name: Install Dependencies - run: msbuild $env:Solution_Name /t:Restore /p:FullTargets=true + run: msbuild $env:Solution_Name /m /t:Restore /p:FullTargets=true - name: Pack - run: msbuild $env:Solution_Name /t:Pack /p:FullTargets=true /p:Configuration=Release /p:PackageOutputPath=../nugets /p:VersionSuffix=build.${{ github.run_number }}.${{ github.run_attempt }} + run: msbuild $env:Solution_Name /m /t:Pack /p:FullTargets=true /p:Configuration=Release /p:PackageOutputPath=../nugets /p:VersionSuffix=build.${{ github.run_number }}.${{ github.run_attempt }} - name: Publish if: ${{ github.event_name == 'push' && github.ref_name == 'main' }} @@ -80,7 +80,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: - name: Nuget Package + name: NuGet Package path: nugets/** diff --git a/.gitignore b/.gitignore index 95ad761..533ca9e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.user *.userosscache *.sln.docstates +*.env # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs @@ -21,16 +22,36 @@ mono_crash.* [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ -x64/ -x86/ + +[Dd]ebug/x64/ +[Dd]ebugPublic/x64/ +[Rr]elease/x64/ +[Rr]eleases/x64/ +bin/x64/ +obj/x64/ + +[Dd]ebug/x86/ +[Dd]ebugPublic/x86/ +[Rr]elease/x86/ +[Rr]eleases/x86/ +bin/x86/ +obj/x86/ + [Ww][Ii][Nn]32/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ +[Aa][Rr][Mm]64[Ee][Cc]/ bld/ -[Bb]in/ [Oo]bj/ +[Oo]ut/ [Ll]og/ -#[Ll]ogs/ +[Ll]ogs/ + +# Build results on 'Bin' directories +**/[Bb]in/* +# Uncomment if you have tasks that rely on *.refresh files to move binaries +# (https://github.com/github/gitignore/pull/3736) +#!**/[Bb]in/*.refresh # Visual Studio 2015/2017 cache/options directory .vs/ @@ -43,12 +64,16 @@ Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* +*.trx # NUnit *.VisualState.xml TestResult.xml nunit-*.xml +# Approval Tests result files +*.received.* + # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ @@ -75,6 +100,7 @@ StyleCopReport.xml *.ilk *.meta *.obj +*.idb *.iobj *.pch *.pdb @@ -155,6 +181,7 @@ coverage*.info # NCrunch _NCrunch_* +.NCrunch_* .*crunch*.local.xml nCrunchTemp_* @@ -296,9 +323,6 @@ node_modules/ # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - # Visual Studio 6 workspace and project file (working project files containing files to include in project) *.dsw *.dsp @@ -316,22 +340,22 @@ node_modules/ _Pvt_Extensions # Paket dependency manager -.paket/paket.exe +**/.paket/paket.exe paket-files/ # FAKE - F# Make -.fake/ +**/.fake/ # CodeRush personal settings -.cr/personal +**/.cr/personal # Python Tools for Visual Studio (PTVS) -__pycache__/ +**/__pycache__/ *.pyc # Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config +#tools/** +#!tools/packages.config # Tabs Studio *.tss @@ -353,15 +377,19 @@ ASALocalRun/ # MSBuild Binary and Structured Log *.binlog +MSBuild_Logs/ + +# AWS SAM Build and Temporary Artifacts folder +.aws-sam # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder -.mfractor/ +**/.mfractor/ # Local History for Visual Studio -.localhistory/ +**/.localhistory/ # Visual Studio History (VSHistory) files .vshistory/ @@ -373,7 +401,7 @@ healthchecksdb MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder -.ionide/ +**/.ionide/ # Fody - auto-generated XML schema FodyWeavers.xsd @@ -384,11 +412,14 @@ FodyWeavers.xsd !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json -*.code-workspace +!.vscode/*.code-snippets # Local History for Visual Studio Code .history/ +# Built Visual Studio Code Extensions +*.vsix + # Windows Installer files from build outputs *.cab *.msi @@ -396,5 +427,5 @@ FodyWeavers.xsd *.msm *.msp -# JetBrains Rider -*.sln.iml \ No newline at end of file +# VS Code C# Dev Kit +*.lscache diff --git a/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj b/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj index 869f801..e22ea8f 100644 --- a/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj +++ b/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj @@ -9,7 +9,7 @@ - net10.0-windows10.0.17763.0 + net10.0-windows10.0.26100.0 @@ -20,15 +20,15 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/AdvancedSharpAdbClient.Tests/Models/FramebufferHeaderTests.cs b/AdvancedSharpAdbClient.Tests/Models/FramebufferHeaderTests.cs index d184a74..5d23e23 100644 --- a/AdvancedSharpAdbClient.Tests/Models/FramebufferHeaderTests.cs +++ b/AdvancedSharpAdbClient.Tests/Models/FramebufferHeaderTests.cs @@ -42,7 +42,7 @@ public void ReadFramebufferTest() } /// - /// Tests the method. + /// Tests the method. /// [Fact] public void ReadFramebufferBySpanTest() @@ -104,7 +104,7 @@ public void ReadFramebufferV2Test() } /// - /// Tests the method. + /// Tests the method. /// [Fact] public void ReadFramebufferV2BySpanTest() diff --git a/AdvancedSharpAdbClient/AdbClient.Async.cs b/AdvancedSharpAdbClient/AdbClient.Async.cs index df0911b..caf23e3 100644 --- a/AdvancedSharpAdbClient/AdbClient.Async.cs +++ b/AdvancedSharpAdbClient/AdbClient.Async.cs @@ -169,7 +169,7 @@ public async Task ExecuteServerCommandAsync(string target, string command, Cance /// public virtual async Task ExecuteServerCommandAsync(string target, string command, IAdbSocket socket, CancellationToken cancellationToken = default) { - DefaultInterpolatedStringHandler request = new(1, 2); + scoped DefaultInterpolatedStringHandler request = new(1, 2); if (!string.IsNullOrWhiteSpace(target)) { request.AppendLiteral(target); @@ -228,7 +228,7 @@ public virtual async Task ExecuteServerCommandAsync(string target, string comman { ArgumentNullException.ThrowIfNull(encoding); - DefaultInterpolatedStringHandler request = new(1, 2); + scoped DefaultInterpolatedStringHandler request = new(1, 2); if (!string.IsNullOrWhiteSpace(target)) { request.AppendLiteral(target); @@ -298,7 +298,7 @@ public virtual async IAsyncEnumerable ExecuteServerEnumerableAsync(strin { ArgumentNullException.ThrowIfNull(encoding); - DefaultInterpolatedStringHandler request = new(1, 2); + scoped DefaultInterpolatedStringHandler request = new(1, 2); if (!string.IsNullOrWhiteSpace(target)) { request.AppendLiteral(target); @@ -361,7 +361,7 @@ public async IAsyncEnumerable RunLogServiceAsync(DeviceData device, [E using IAdbSocket socket = CreateAdbSocket(); await socket.SetDeviceAsync(device, cancellationToken).ConfigureAwait(false); - DefaultInterpolatedStringHandler request = new(19, logNames.Length); + scoped DefaultInterpolatedStringHandler request = new(19, logNames.Length); request.AppendLiteral("shell:logcat -B"); foreach (LogId logName in logNames) @@ -415,7 +415,7 @@ public async Task RunLogServiceAsync(DeviceData device, Action message using IAdbSocket socket = CreateAdbSocket(); await socket.SetDeviceAsync(device, cancellationToken).ConfigureAwait(false); - DefaultInterpolatedStringHandler request = new(19, logNames.Length); + scoped DefaultInterpolatedStringHandler request = new(19, logNames.Length); request.AppendLiteral("shell:logcat -B"); foreach (LogId logName in logNames) @@ -584,7 +584,7 @@ public virtual async Task InstallAsync(DeviceData device, Stream apk, Action InstallCreateAsync(DeviceData device, CancellationToke using IAdbSocket socket = CreateAdbSocket(); await socket.SetDeviceAsync(device, cancellationToken).ConfigureAwait(false); - DefaultInterpolatedStringHandler requestBuilder = new(33, arguments?.Length ?? 0); + scoped DefaultInterpolatedStringHandler requestBuilder = new(33, arguments?.Length ?? 0); requestBuilder.AppendLiteral("exec:cmd package 'install-create'"); if (arguments != null) @@ -784,7 +784,7 @@ public async Task InstallCreateAsync(DeviceData device, string packageNa using IAdbSocket socket = CreateAdbSocket(); await socket.SetDeviceAsync(device, cancellationToken).ConfigureAwait(false); - DefaultInterpolatedStringHandler requestBuilder = new(37 + packageName.Length, arguments?.Length ?? 0); + scoped DefaultInterpolatedStringHandler requestBuilder = new(37 + packageName.Length, arguments?.Length ?? 0); requestBuilder.AppendLiteral("exec:cmd package 'install-create'"); requestBuilder.AppendFormatted(" -p "); requestBuilder.AppendLiteral(packageName); @@ -972,7 +972,7 @@ public virtual async Task InstallAsync(DeviceData device, IRandomAccessStream ap using IAdbSocket socket = CreateAdbSocket(); await socket.SetDeviceAsync(device, cancellationToken).ConfigureAwait(false); - DefaultInterpolatedStringHandler requestBuilder = new(30, (arguments?.Length ?? 0) + 1); + scoped DefaultInterpolatedStringHandler requestBuilder = new(30, (arguments?.Length ?? 0) + 1); requestBuilder.AppendLiteral("exec:cmd package 'install'"); if (arguments != null) @@ -1251,7 +1251,7 @@ public async Task UninstallAsync(DeviceData device, string packageName, Cancella using IAdbSocket socket = CreateAdbSocket(); await socket.SetDeviceAsync(device, cancellationToken).ConfigureAwait(false); - DefaultInterpolatedStringHandler requestBuilder = new(29, (arguments?.Length ?? 0) + 1); + scoped DefaultInterpolatedStringHandler requestBuilder = new(29, (arguments?.Length ?? 0) + 1); requestBuilder.AppendLiteral("exec:cmd package 'uninstall'"); if (arguments != null) diff --git a/AdvancedSharpAdbClient/AdbClient.cs b/AdvancedSharpAdbClient/AdbClient.cs index 44dbcc7..e236ade 100644 --- a/AdvancedSharpAdbClient/AdbClient.cs +++ b/AdvancedSharpAdbClient/AdbClient.cs @@ -185,12 +185,12 @@ public static byte[] CreateAdbForwardRequest(string address, int port) /// /// The request to form. /// An array containing ####req. - public static byte[] FormAdbRequest(ReadOnlySpan req) + public static byte[] FormAdbRequest(scoped ReadOnlySpan req) { int payloadLength = Encoding.GetByteCount(req); #if NET10_0_OR_GREATER - DefaultInterpolatedStringHandler resultStr = $"{payloadLength:X4}{req}"; - ReadOnlySpan text = resultStr.Text; + scoped DefaultInterpolatedStringHandler resultStr = $"{payloadLength:X4}{req}"; + scoped ReadOnlySpan text = resultStr.Text; int byteCount = Encoding.GetByteCount(text); byte[] result = new byte[byteCount]; _ = Encoding.GetBytes(text, result); @@ -207,13 +207,13 @@ public static byte[] FormAdbRequest(ReadOnlySpan req) /// The address. /// The port. /// This returns an array containing "####tcp:{port}:{addStr}". - public static byte[] CreateAdbForwardRequest(ReadOnlySpan address, int port) + public static byte[] CreateAdbForwardRequest(scoped ReadOnlySpan address, int port) { #if NET10_0_OR_GREATER - DefaultInterpolatedStringHandler request = address.IsEmpty ? (DefaultInterpolatedStringHandler)$"tcp:{port}" : $"tcp:{port}:{address}"; + scoped DefaultInterpolatedStringHandler request = address.IsEmpty ? (DefaultInterpolatedStringHandler)$"tcp:{port}" : $"tcp:{port}:{address}"; return FormAdbRequest(request.Text); #else - string request = address == null ? $"tcp:{port}" : $"tcp:{port}:{address}"; + string request = address.Length > 0 ? $"tcp:{port}:{address}" : $"tcp:{port}"; return FormAdbRequest(request); #endif } @@ -372,7 +372,7 @@ public void ExecuteServerCommand(string target, string command) /// public virtual void ExecuteServerCommand(string target, string command, IAdbSocket socket) { - DefaultInterpolatedStringHandler request = new(1, 2); + scoped DefaultInterpolatedStringHandler request = new(1, 2); if (!string.IsNullOrWhiteSpace(target)) { request.AppendLiteral(target); @@ -422,7 +422,7 @@ public virtual void ExecuteServerCommand(string target, string command, IAdbSock { ArgumentNullException.ThrowIfNull(encoding); - DefaultInterpolatedStringHandler request = new(1, 2); + scoped DefaultInterpolatedStringHandler request = new(1, 2); if (!string.IsNullOrWhiteSpace(target)) { request.AppendLiteral(target); @@ -484,7 +484,7 @@ public virtual IEnumerable ExecuteServerEnumerable(string target, string { ArgumentNullException.ThrowIfNull(encoding); - DefaultInterpolatedStringHandler request = new(1, 2); + scoped DefaultInterpolatedStringHandler request = new(1, 2); if (!string.IsNullOrWhiteSpace(target)) { request.AppendLiteral(target); @@ -540,7 +540,7 @@ public IEnumerable RunLogService(DeviceData device, params LogId[] log using IAdbSocket socket = CreateAdbSocket(); socket.SetDevice(device); - DefaultInterpolatedStringHandler request = new(19, logNames.Length); + scoped DefaultInterpolatedStringHandler request = new(19, logNames.Length); request.AppendLiteral("shell:logcat -B"); foreach (LogId logName in logNames) @@ -579,7 +579,7 @@ public IEnumerable RunLogService(DeviceData device, params LogId[] log } /// - public void RunLogService(DeviceData device, Action messageSink, in bool isCancelled = false, params LogId[] logNames) + public void RunLogService(DeviceData device, Action messageSink, scoped in bool isCancelled = false, params LogId[] logNames) { EnsureDevice(device); ArgumentNullException.ThrowIfNull(messageSink); @@ -589,7 +589,7 @@ public void RunLogService(DeviceData device, Action messageSink, in bo using IAdbSocket socket = CreateAdbSocket(); socket.SetDevice(device); - DefaultInterpolatedStringHandler request = new(19, logNames.Length); + scoped DefaultInterpolatedStringHandler request = new(19, logNames.Length); request.AppendLiteral("shell:logcat -B"); foreach (LogId logName in logNames) @@ -762,7 +762,7 @@ public virtual void Install(DeviceData device, Stream apk, Action GetFeatureSet(DeviceData device) /// A object to validate. /// The name of the parameter with which corresponds. /// The does not have a valid serial number. - protected static void EnsureDevice(in DeviceData device, [CallerArgumentExpression(nameof(device))] string? paramName = "device") + protected static void EnsureDevice(scoped in DeviceData device, [CallerArgumentExpression(nameof(device))] string? paramName = "device") { if (device.IsEmpty) { diff --git a/AdvancedSharpAdbClient/AdbServer.cs b/AdvancedSharpAdbClient/AdbServer.cs index 9a78263..e502ce8 100644 --- a/AdvancedSharpAdbClient/AdbServer.cs +++ b/AdvancedSharpAdbClient/AdbServer.cs @@ -149,7 +149,11 @@ public AdbServer(Func adbSocketFactory, Func /// Gets or sets the default instance of the interface. /// - public static IAdbServer Instance { get; set; } = new AdbServer(); + public static IAdbServer Instance + { + get => field ??= new AdbServer(); + set; + } /// /// if is starting adb server; otherwise, . diff --git a/AdvancedSharpAdbClient/AdbSocket.cs b/AdvancedSharpAdbClient/AdbSocket.cs index 3262cce..91bfbea 100644 --- a/AdvancedSharpAdbClient/AdbSocket.cs +++ b/AdvancedSharpAdbClient/AdbSocket.cs @@ -91,7 +91,7 @@ public AdbSocket(string host, int port, ILogger? logger = null) /// /// The reply. /// if the specified reply is okay; otherwise, . - public static bool IsOkay(ReadOnlySpan reply) => AdbClient.Encoding.GetString(reply).Equals("OKAY"); + public static bool IsOkay(scoped ReadOnlySpan reply) => AdbClient.Encoding.GetString(reply).Equals("OKAY"); #endif /// @@ -219,7 +219,7 @@ public void SendAdbRequest(string request) #if NET10_0_OR_GREATER /// - public void SendAdbRequest(DefaultInterpolatedStringHandler request) + public void SendAdbRequest(scoped DefaultInterpolatedStringHandler request) { byte[] data = AdbClient.FormAdbRequest(request.Text); if (!Write(data)) @@ -358,7 +358,7 @@ public AdbResponse ReadAdbResponse() #if COMP_NETSTANDARD2_1 /// - public virtual void Send(ReadOnlySpan data) + public virtual void Send(scoped ReadOnlySpan data) { try { @@ -376,7 +376,7 @@ public virtual void Send(ReadOnlySpan data) } /// - public virtual int Read(Span data) + public virtual int Read(scoped Span data) { int count = -1; int totalRead = 0; @@ -484,7 +484,7 @@ protected virtual bool Write(byte[] data) /// The data to send. /// Returns if all data was written; otherwise, . /// This uses the default time out value. - protected virtual bool Write(ReadOnlySpan data) + protected virtual bool Write(scoped ReadOnlySpan data) { try { @@ -547,7 +547,7 @@ protected string ReplyToString(byte[] reply) /// /// A array that represents the ADB reply. /// A that represents the ADB reply. - protected string ReplyToString(ReadOnlySpan reply) + protected string ReplyToString(scoped ReadOnlySpan reply) { string result; try diff --git a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj index dee57de..96b8bc8 100644 --- a/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj +++ b/AdvancedSharpAdbClient/AdvancedSharpAdbClient.csproj @@ -19,7 +19,7 @@ $(NoWarn);NU1603;NU1605 - $(TargetFrameworks);net6.0;netcoreapp2.1;netcoreapp3.1 + $(TargetFrameworks);net6.0;net6.0-windows10.0.17763.0;netcoreapp2.1;netcoreapp3.1 $(TargetFrameworks);net4.0-client;net4.6.1 $(TargetFrameworks);netcore5.0;uap10.0;uap10.0.15138.0 @@ -34,6 +34,7 @@ System.Diagnostics.CodeAnalysis.NotNullAttribute; System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute; System.Diagnostics.CodeAnalysis.NotNullWhenAttribute; + System.Diagnostics.CodeAnalysis.StringSyntaxAttribute; System.Diagnostics.StackTraceHiddenAttribute; System.Index; System.Range; @@ -64,11 +65,11 @@ - + - + + True diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs index babc4cd..1f9a461 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.Async.cs @@ -25,6 +25,7 @@ public static partial class DeviceExtensions /// The command to execute. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData device, string command, CancellationToken cancellationToken = default) => client.ExecuteRemoteCommandAsync(command, device, cancellationToken); @@ -37,6 +38,7 @@ public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData d /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData device, string command, IShellOutputReceiver? receiver, CancellationToken cancellationToken = default) => client.ExecuteRemoteCommandAsync(command, device, receiver, AdbClient.Encoding, cancellationToken); @@ -49,6 +51,7 @@ public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData d /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData device, string command, Func? predicate, CancellationToken cancellationToken = default) => client.ExecuteRemoteCommandAsync(command, device, predicate.AsShellOutputReceiver(), AdbClient.Encoding, cancellationToken); @@ -59,6 +62,7 @@ public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData d /// The device on which to run the command. /// A which can be used to cancel the asynchronous operation. /// A which returns a containing current hierarchy. + [MethodImpl((MethodImplOptions)0x100)] public static Task DumpScreenAsync(this IAdbClient client, DeviceData device, CancellationToken cancellationToken = default) => new DeviceClient(client, device).DumpScreenAsync(cancellationToken); @@ -70,6 +74,7 @@ public static Task ExecuteShellCommandAsync(this IAdbClient client, DeviceData d /// The to click. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ClickAsync(this IAdbClient client, DeviceData device, Point point, CancellationToken cancellationToken = default) => new DeviceClient(client, device).ClickAsync(point, cancellationToken); @@ -83,6 +88,7 @@ public static Task ClickAsync(this IAdbClient client, DeviceData device, Point p /// The time spent in swiping. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task SwipeAsync(this IAdbClient client, DeviceData device, Point first, Point second, long speed, CancellationToken cancellationToken = default) => new DeviceClient(client, device).SwipeAsync(first, second, speed, cancellationToken); @@ -94,6 +100,7 @@ public static Task SwipeAsync(this IAdbClient client, DeviceData device, Point f /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static Task GetAppStatusAsync(this IAdbClient client, DeviceData device, string packageName, CancellationToken cancellationToken = default) => new DeviceClient(client, device).GetAppStatusAsync(packageName, cancellationToken); @@ -107,6 +114,7 @@ public static Task GetAppStatusAsync(this IAdbClient client, DeviceDa /// 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 . + [MethodImpl((MethodImplOptions)0x100)] public static Task FindElementAsync(this IAdbClient client, DeviceData device, string xpath = "hierarchy/node", CancellationToken cancellationToken = default) => new DeviceClient(client, device).FindElementAsync(xpath, cancellationToken); @@ -119,6 +127,7 @@ public static Task GetAppStatusAsync(this IAdbClient client, DeviceDa /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static Task> FindElementsAsync(this IAdbClient client, DeviceData device, string xpath = "hierarchy/node", CancellationToken cancellationToken = default) => new DeviceClient(client, device).FindElementsAsync(xpath, cancellationToken); @@ -132,6 +141,7 @@ public static Task> FindElementsAsync(this IAdbClient clien /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static IAsyncEnumerable FindAsyncElements(this IAdbClient client, DeviceData device, string xpath = "hierarchy/node", CancellationToken cancellationToken = default) => new DeviceClient(client, device).FindAsyncElements(xpath, cancellationToken); #endif @@ -145,6 +155,7 @@ public static IAsyncEnumerable FindAsyncElements(this IAdbClient client /// The key event to send. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task SendKeyEventAsync(this IAdbClient client, DeviceData device, string key, CancellationToken cancellationToken = default) => new DeviceClient(client, device).SendKeyEventAsync(key, cancellationToken); @@ -156,6 +167,7 @@ public static Task SendKeyEventAsync(this IAdbClient client, DeviceData device, /// The text to send. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task SendTextAsync(this IAdbClient client, DeviceData device, string text, CancellationToken cancellationToken = default) => new DeviceClient(client, device).SendTextAsync(text, cancellationToken); @@ -167,6 +179,7 @@ public static Task SendTextAsync(this IAdbClient client, DeviceData device, stri /// The length of text to clear. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ClearInputAsync(this IAdbClient client, DeviceData device, int charCount, CancellationToken cancellationToken = default) => new DeviceClient(client, device).ClearInputAsync(charCount, cancellationToken); @@ -177,6 +190,7 @@ public static Task ClearInputAsync(this IAdbClient client, DeviceData device, in /// The device on which to click BACK button. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ClickBackButtonAsync(this IAdbClient client, DeviceData device, CancellationToken cancellationToken = default) => new DeviceClient(client, device).ClickBackButtonAsync(cancellationToken); @@ -187,6 +201,7 @@ public static Task ClickBackButtonAsync(this IAdbClient client, DeviceData devic /// The device on which to click HOME button. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ClickHomeButtonAsync(this IAdbClient client, DeviceData device, CancellationToken cancellationToken = default) => new DeviceClient(client, device).ClickHomeButtonAsync(cancellationToken); @@ -198,6 +213,7 @@ public static Task ClickHomeButtonAsync(this IAdbClient client, DeviceData devic /// The package name of the application to start. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task StartAppAsync(this IAdbClient client, DeviceData device, string packageName, CancellationToken cancellationToken = default) => client.ExecuteShellCommandAsync(device, $"monkey -p {packageName} 1", cancellationToken); @@ -209,6 +225,7 @@ public static Task StartAppAsync(this IAdbClient client, DeviceData device, stri /// The package name of the application to stop. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task StopAppAsync(this IAdbClient client, DeviceData device, string packageName, CancellationToken cancellationToken = default) => client.ExecuteShellCommandAsync(device, $"am force-stop {packageName}", cancellationToken); @@ -296,6 +313,7 @@ public static async Task StatExAsync(this IAdbClient client, D /// A that can be used to cancel the task. /// A which returns a object that contains information about the file. /// The file size will be cut off at 4 GiB due to the use of a 32-bit unsigned integer. + [MethodImpl((MethodImplOptions)0x100)] public static Task StatAsync(this IAdbClient client, DeviceData device, string path, bool useV2, CancellationToken cancellationToken = default) => useV2 ? client.StatExAsync(device, path, cancellationToken).ContinueWith(x => x.Result as IFileStatistics) : client.StatAsync(device, path, cancellationToken).ContinueWith(x => x.Result as IFileStatistics); @@ -338,6 +356,7 @@ public static async Task> GetDirectoryListingExAsync(this /// A that can be used to cancel the task. /// A which returns for each child item of the directory, a object with information of the item. /// File size bigger than 4GB need V2, and V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static Task> GetDirectoryListingAsync(this IAdbClient client, DeviceData device, string remotePath, bool useV2, CancellationToken cancellationToken = default) => #if NETFRAMEWORK && !NET40_OR_GREATER useV2 ? client.GetDirectoryListingExAsync(device, remotePath, cancellationToken).ContinueWith(x => x.Result.OfType()) : client.GetDirectoryListingAsync(device, remotePath, cancellationToken).ContinueWith(x => x.Result.OfType()); @@ -391,6 +410,7 @@ public static async IAsyncEnumerable GetDirectoryAsyncListingE /// A that can be used to cancel the task. /// An which returns for each child item of the directory, a object with information of the item. /// File size bigger than 4GB need V2, and V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static IAsyncEnumerable GetDirectoryAsyncListing(this IAdbClient client, DeviceData device, string remotePath, bool useV2, CancellationToken cancellationToken = default) => useV2 ? client.GetDirectoryAsyncListingEx(device, remotePath, cancellationToken) : client.GetDirectoryAsyncListing(device, remotePath, cancellationToken); #endif @@ -449,11 +469,9 @@ public static async Task> GetEnvironmentVariablesAsyn /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install. /// A which represents the asynchronous operation. - public static Task InstallPackageAsync(this IAdbClient client, DeviceData device, string packageFilePath, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.InstallPackageAsync(packageFilePath, callback, cancellationToken, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task InstallPackageAsync(this IAdbClient client, DeviceData device, string packageFilePath, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallPackageAsync(packageFilePath, callback, cancellationToken, arguments); /// /// Asynchronously installs Android multiple application on device. @@ -467,11 +485,8 @@ public static Task InstallPackageAsync(this IAdbClient client, DeviceData device /// 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 static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.InstallMultiplePackageAsync(basePackageFilePath, splitPackageFilePaths, callback, cancellationToken, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) => new PackageManager(client, device, skipInit: true).InstallMultiplePackageAsync(basePackageFilePath, splitPackageFilePaths, callback, cancellationToken, arguments); /// /// Asynchronously installs Android multiple application on device. @@ -485,11 +500,9 @@ public static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceDat /// 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 static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.InstallMultiplePackageAsync(splitPackageFilePaths, packageName, callback, cancellationToken, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, CancellationToken cancellationToken = default, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallMultiplePackageAsync(splitPackageFilePaths, packageName, callback, cancellationToken, arguments); #if !NETFRAMEWORK || NET40_OR_GREATER /// @@ -548,11 +561,9 @@ public static async Task PushAsync(this IAdbClient client, DeviceData device, /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install. /// A which represents the asynchronous operation. - public static Task InstallPackageAsync(this IAdbClient client, DeviceData device, string packageFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.InstallPackageAsync(packageFilePath, progress, cancellationToken, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task InstallPackageAsync(this IAdbClient client, DeviceData device, string packageFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallPackageAsync(packageFilePath, progress, cancellationToken, arguments); /// /// Asynchronously installs Android multiple application on device. @@ -566,11 +577,9 @@ public static Task InstallPackageAsync(this IAdbClient client, DeviceData device /// 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 static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.InstallMultiplePackageAsync(basePackageFilePath, splitPackageFilePaths, progress, cancellationToken, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallMultiplePackageAsync(basePackageFilePath, splitPackageFilePaths, progress, cancellationToken, arguments); /// /// Asynchronously installs Android multiple application on device. @@ -584,11 +593,9 @@ public static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceDat /// 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 static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.InstallMultiplePackageAsync(splitPackageFilePaths, packageName, progress, cancellationToken, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task InstallMultiplePackageAsync(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallMultiplePackageAsync(splitPackageFilePaths, packageName, progress, cancellationToken, arguments); #if NET7_0_OR_GREATER /// @@ -647,11 +654,9 @@ public static async Task PushAsync(this IAdbClient client, DeviceData device, /// The name of the package to uninstall. /// The arguments to pass to pm uninstall. /// A which represents the asynchronous operation. - public static Task UninstallPackageAsync(this IAdbClient client, DeviceData device, string packageName, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.UninstallPackageAsync(packageName, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task UninstallPackageAsync(this IAdbClient client, DeviceData device, string packageName, params string[] arguments) => + new PackageManager(client, device, skipInit: true).UninstallPackageAsync(packageName, arguments); /// /// Asynchronously uninstalls a package from the device. @@ -662,11 +667,9 @@ public static Task UninstallPackageAsync(this IAdbClient client, DeviceData devi /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to pm uninstall. /// A which represents the asynchronous operation. - public static Task UninstallPackageAsync(this IAdbClient client, DeviceData device, string packageName, CancellationToken cancellationToken, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.UninstallPackageAsync(packageName, cancellationToken, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task UninstallPackageAsync(this IAdbClient client, DeviceData device, string packageName, CancellationToken cancellationToken, params string[] arguments) => + new PackageManager(client, device, skipInit: true).UninstallPackageAsync(packageName, cancellationToken, arguments); /// /// Asynchronously requests the version information from the device. @@ -676,11 +679,9 @@ public static Task UninstallPackageAsync(this IAdbClient client, DeviceData devi /// 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 static Task GetPackageVersionAsync(this IAdbClient client, DeviceData device, string packageName, CancellationToken cancellationToken = default) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.GetVersionInfoAsync(packageName, cancellationToken); - } + [MethodImpl((MethodImplOptions)0x100)] + public static Task GetPackageVersionAsync(this IAdbClient client, DeviceData device, string packageName, CancellationToken cancellationToken = default) => + new PackageManager(client, device, skipInit: true).GetVersionInfoAsync(packageName, cancellationToken); /// /// Asynchronously lists all processes running on the device. diff --git a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs index 6761601..1473ff9 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/DeviceExtensions.cs @@ -24,6 +24,7 @@ public static partial class DeviceExtensions /// The to use when executing the command. /// The device on which to run the command. /// The command to execute. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteShellCommand(this IAdbClient client, DeviceData device, string command) => client.ExecuteRemoteCommand(command, device); @@ -34,6 +35,7 @@ public static void ExecuteShellCommand(this IAdbClient client, DeviceData device /// The device on which to run the command. /// The command to execute. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteShellCommand(this IAdbClient client, DeviceData device, string command, IShellOutputReceiver? receiver) => client.ExecuteRemoteCommand(command, device, receiver, AdbClient.Encoding); @@ -44,6 +46,7 @@ public static void ExecuteShellCommand(this IAdbClient client, DeviceData device /// The device on which to run the command. /// The command to execute. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteShellCommand(this IAdbClient client, DeviceData device, string command, Func? predicate) => client.ExecuteRemoteCommand(command, device, predicate.AsShellOutputReceiver(), AdbClient.Encoding); @@ -53,6 +56,7 @@ 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. /// A containing current hierarchy. + [MethodImpl((MethodImplOptions)0x100)] public static XmlDocument? DumpScreen(this IAdbClient client, DeviceData device) => new DeviceClient(client, device).DumpScreen(); @@ -62,6 +66,7 @@ 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. + [MethodImpl((MethodImplOptions)0x100)] public static void Click(this IAdbClient client, DeviceData device, Point point) => new DeviceClient(client, device).Click(point); @@ -73,6 +78,7 @@ public static void Click(this IAdbClient client, DeviceData device, Point point) /// The start . /// The end . /// The time spent in swiping. + [MethodImpl((MethodImplOptions)0x100)] public static void Swipe(this IAdbClient client, DeviceData device, Point first, Point second, long speed) => new DeviceClient(client, device).Swipe(first, second, speed); @@ -83,6 +89,7 @@ public static void Swipe(this IAdbClient client, DeviceData device, Point first, /// The device on which to clear the input text. /// The package name of the app to check. /// The of the app. Foreground, stopped or running in background. + [MethodImpl((MethodImplOptions)0x100)] public static AppStatus GetAppStatus(this IAdbClient client, DeviceData device, string packageName) => new DeviceClient(client, device).GetAppStatus(packageName); @@ -96,6 +103,7 @@ public static AppStatus GetAppStatus(this IAdbClient client, DeviceData device, /// The timeout for waiting the element. /// Only check once if or . /// The of . + [MethodImpl((MethodImplOptions)0x100)] public static Element? FindElement(this IAdbClient client, DeviceData device, string xpath = "hierarchy/node", TimeSpan timeout = default) => new DeviceClient(client, device).FindElement(xpath, timeout); @@ -108,6 +116,7 @@ public static AppStatus GetAppStatus(this IAdbClient client, DeviceData device, /// The timeout for waiting the elements. /// Only check once if or . /// The of has got. + [MethodImpl((MethodImplOptions)0x100)] public static IEnumerable FindElements(this IAdbClient client, DeviceData device, string xpath = "hierarchy/node", TimeSpan timeout = default) => new DeviceClient(client, device).FindElements(xpath, timeout); #endif @@ -118,6 +127,7 @@ public static IEnumerable FindElements(this IAdbClient client, DeviceDa /// An instance of a class that implements the interface. /// The device on which to clear the input text. /// The key event to send. + [MethodImpl((MethodImplOptions)0x100)] public static void SendKeyEvent(this IAdbClient client, DeviceData device, string key) => new DeviceClient(client, device).SendKeyEvent(key); @@ -127,6 +137,7 @@ public static void SendKeyEvent(this IAdbClient client, DeviceData device, strin /// An instance of a class that implements the interface. /// The device on which to clear the input text. /// The text to send. + [MethodImpl((MethodImplOptions)0x100)] public static void SendText(this IAdbClient client, DeviceData device, string text) => new DeviceClient(client, device).SendText(text); @@ -136,6 +147,7 @@ public static void SendText(this IAdbClient client, DeviceData device, string te /// An instance of a class that implements the interface. /// The device on which to clear the input text. /// The length of text to clear. + [MethodImpl((MethodImplOptions)0x100)] public static void ClearInput(this IAdbClient client, DeviceData device, int charCount) => new DeviceClient(client, device).ClearInput(charCount); @@ -144,6 +156,7 @@ public static void ClearInput(this IAdbClient client, DeviceData device, int cha /// /// An instance of a class that implements the interface. /// The device on which to click BACK button. + [MethodImpl((MethodImplOptions)0x100)] public static void ClickBackButton(this IAdbClient client, DeviceData device) => new DeviceClient(client, device).ClickBackButton(); @@ -152,6 +165,7 @@ public static void ClickBackButton(this IAdbClient client, DeviceData device) => /// /// An instance of a class that implements the interface. /// The device on which to click HOME button. + [MethodImpl((MethodImplOptions)0x100)] public static void ClickHomeButton(this IAdbClient client, DeviceData device) => new DeviceClient(client, device).ClickHomeButton(); @@ -161,6 +175,7 @@ public static void ClickHomeButton(this IAdbClient client, DeviceData device) => /// An instance of a class that implements the interface. /// The device on which to click HOME button. /// The package name of the application to start. + [MethodImpl((MethodImplOptions)0x100)] public static void StartApp(this IAdbClient client, DeviceData device, string packageName) => client.ExecuteShellCommand(device, $"monkey -p {packageName} 1"); @@ -170,6 +185,7 @@ public static void StartApp(this IAdbClient client, DeviceData device, string pa /// An instance of a class that implements the interface. /// The device on which to click HOME button. /// The package name of the application to stop. + [MethodImpl((MethodImplOptions)0x100)] public static void StopApp(this IAdbClient client, DeviceData device, string packageName) => client.ExecuteShellCommand(device, $"am force-stop {packageName}"); @@ -188,7 +204,7 @@ public static void Pull(this IAdbClient client, DeviceData device, string remotePath, Stream stream, Action? callback = null, bool useV2 = false, - in bool isCancelled = false) + scoped in bool isCancelled = false) { using ISyncService service = Factories.SyncServiceFactory(client, device); service.Pull(remotePath, stream, callback, useV2, in isCancelled); @@ -211,7 +227,7 @@ public static void Push(this IAdbClient client, DeviceData device, string remotePath, Stream stream, UnixFileStatus permission, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, - in bool isCancelled = false) + scoped in bool isCancelled = false) { using ISyncService service = Factories.SyncServiceFactory(client, device); service.Push(stream, remotePath, permission, timestamp, callback, useV2, in isCancelled); @@ -254,6 +270,7 @@ public static FileStatisticsEx StatEx(this IAdbClient client, DeviceData device, /// to use ; otherwise, use . /// A object that represents the file. /// File size bigger than 4GB need V2, and V2 need Android 8 or above. + [MethodImpl((MethodImplOptions)0x100)] public static IFileStatistics Stat(this IAdbClient client, DeviceData device, string path, bool useV2) => useV2 ? client.StatEx(device, path) : client.Stat(device, path); @@ -299,6 +316,7 @@ public static IEnumerable GetDirectoryListingEx(this IAdbClien /// to use ; otherwise, use . /// For each child item of the directory, a object with information of the item. /// V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static IEnumerable GetDirectoryListing(this IAdbClient client, DeviceData device, string remotePath, bool useV2) => #if NETFRAMEWORK && !NET40_OR_GREATER useV2 ? client.GetDirectoryListingEx(device, remotePath).OfType() : client.GetDirectoryListing(device, remotePath).OfType(); @@ -355,11 +373,9 @@ public static Dictionary GetEnvironmentVariables(this IAdbClient /// 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 static void InstallPackage(this IAdbClient client, DeviceData device, string packageFilePath, Action? callback = null, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - manager.InstallPackage(packageFilePath, callback, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static void InstallPackage(this IAdbClient client, DeviceData device, string packageFilePath, Action? callback = null, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallPackage(packageFilePath, callback, arguments); /// /// Installs Android multiple application on device. @@ -371,11 +387,9 @@ public static void InstallPackage(this IAdbClient client, DeviceData device, str /// 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 static void InstallMultiplePackage(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - manager.InstallMultiplePackage(basePackageFilePath, splitPackageFilePaths, callback, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static void InstallMultiplePackage(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, Action? callback = null, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallMultiplePackage(basePackageFilePath, splitPackageFilePaths, callback, arguments); /// /// Installs Android multiple application on device. @@ -387,11 +401,9 @@ public static void InstallMultiplePackage(this IAdbClient client, DeviceData dev /// 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 static void InstallMultiplePackage(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - manager.InstallMultiplePackage(splitPackageFilePaths, packageName, callback, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static void InstallMultiplePackage(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, Action? callback = null, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallMultiplePackage(splitPackageFilePaths, packageName, callback, arguments); #if !NETFRAMEWORK || NET40_OR_GREATER /// @@ -409,7 +421,7 @@ public static void Pull(this IAdbClient client, DeviceData device, string remotePath, Stream stream, IProgress? progress = null, bool useV2 = false, - in bool isCancelled = false) + scoped in bool isCancelled = false) { using ISyncService service = Factories.SyncServiceFactory(client, device); service.Pull(remotePath, stream, progress.AsAction(), useV2, in isCancelled); @@ -432,7 +444,7 @@ public static void Push(this IAdbClient client, DeviceData device, string remotePath, Stream stream, UnixFileStatus permission, DateTimeOffset timestamp, IProgress? progress = null, bool useV2 = false, - in bool isCancelled = false) + scoped in bool isCancelled = false) { using ISyncService service = Factories.SyncServiceFactory(client, device); service.Push(stream, remotePath, permission, timestamp, progress.AsAction(), useV2, in isCancelled); @@ -447,11 +459,9 @@ public static void Push(this IAdbClient client, DeviceData device, /// 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 static void InstallPackage(this IAdbClient client, DeviceData device, string packageFilePath, IProgress? progress = null, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - manager.InstallPackage(packageFilePath, progress, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static void InstallPackage(this IAdbClient client, DeviceData device, string packageFilePath, IProgress? progress = null, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallPackage(packageFilePath, progress, arguments); /// /// Installs Android multiple application on device. @@ -463,11 +473,9 @@ public static void InstallPackage(this IAdbClient client, DeviceData device, str /// 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 static void InstallMultiplePackage(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - manager.InstallMultiplePackage(basePackageFilePath, splitPackageFilePaths, progress, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static void InstallMultiplePackage(this IAdbClient client, DeviceData device, string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallMultiplePackage(basePackageFilePath, splitPackageFilePaths, progress, arguments); /// /// Installs Android multiple application on device. @@ -479,11 +487,9 @@ public static void InstallMultiplePackage(this IAdbClient client, DeviceData dev /// 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 static void InstallMultiplePackage(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - manager.InstallMultiplePackage(splitPackageFilePaths, packageName, progress, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static void InstallMultiplePackage(this IAdbClient client, DeviceData device, IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, params string[] arguments) => + new PackageManager(client, device, skipInit: true).InstallMultiplePackage(splitPackageFilePaths, packageName, progress, arguments); #if NET7_0_OR_GREATER /// @@ -503,7 +509,7 @@ public static void Push(this IAdbClient client, DeviceData device, string remotePath, Stream stream, UnixFileMode permission, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, - in bool isCancelled = false) + scoped in bool isCancelled = false) { using ISyncService service = Factories.SyncServiceFactory(client, device); service.Push(stream, remotePath, (UnixFileStatus)permission, timestamp, callback, useV2, in isCancelled); @@ -526,7 +532,7 @@ public static void Push(this IAdbClient client, DeviceData device, string remotePath, Stream stream, UnixFileMode permission, DateTimeOffset timestamp, IProgress? progress, bool useV2 = false, - in bool isCancelled = false) + scoped in bool isCancelled = false) { using ISyncService service = Factories.SyncServiceFactory(client, device); service.Push(stream, remotePath, (UnixFileStatus)permission, timestamp, progress.AsAction(), useV2, in isCancelled); @@ -541,11 +547,9 @@ public static void Push(this IAdbClient client, DeviceData device, /// The device on which to uninstall the package. /// The name of the package to uninstall. /// The arguments to pass to pm uninstall. - public static void UninstallPackage(this IAdbClient client, DeviceData device, string packageName, params string[] arguments) - { - PackageManager manager = new(client, device, skipInit: true); - manager.UninstallPackage(packageName, arguments); - } + [MethodImpl((MethodImplOptions)0x100)] + public static void UninstallPackage(this IAdbClient client, DeviceData device, string packageName, params string[] arguments) => + new PackageManager(client, device, skipInit: true).UninstallPackage(packageName, arguments); /// /// Requests the version information from the device. @@ -553,11 +557,9 @@ public static void UninstallPackage(this IAdbClient client, DeviceData device, s /// The connection to the adb server. /// The device on which to uninstall the package. /// The name of the package from which to get the application version. - public static VersionInfo GetPackageVersion(this IAdbClient client, DeviceData device, string packageName) - { - PackageManager manager = new(client, device, skipInit: true); - return manager.GetVersionInfo(packageName); - } + [MethodImpl((MethodImplOptions)0x100)] + public static VersionInfo GetPackageVersion(this IAdbClient client, DeviceData device, string packageName) => + new PackageManager(client, device, skipInit: true).GetVersionInfo(packageName); /// /// Lists all processes running on the device. @@ -625,7 +627,7 @@ public static List ListProcesses(this IAdbClient client, DeviceD // Doing cat on each file one by one takes too much time. Doing cat on all of them at the same time doesn't work // either, because the command line would be too long. // So we do it 25 processes at at time. - DefaultInterpolatedStringHandler catBuilder = new(3, pids.Count); + scoped DefaultInterpolatedStringHandler catBuilder = new(3, pids.Count); ProcessOutputReceiver processOutputReceiver = new(); catBuilder.AppendLiteral("cat"); diff --git a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs index 0a088d8..7744377 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.Async.cs @@ -23,7 +23,7 @@ public Task RefreshPackagesAsync(CancellationToken cancellationToken = default) { ValidateDevice(); - DefaultInterpolatedStringHandler requestBuilder = new(19, Arguments?.Length ?? 0); + scoped DefaultInterpolatedStringHandler requestBuilder = new(19, Arguments?.Length ?? 0); requestBuilder.AppendLiteral(ListFull); if (Arguments != null) @@ -84,7 +84,7 @@ public async Task InstallRemotePackageAsync(string remoteFilePath, Action /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install. /// A which represents the asynchronous operation. - public async Task InstallPackageAsync(string packageFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => - await InstallPackageAsync(packageFilePath, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); + [MethodImpl((MethodImplOptions)0x100)] + public Task InstallPackageAsync(string packageFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + InstallPackageAsync(packageFilePath, progress.AsAction(), cancellationToken, arguments); /// /// Asynchronously installs the application package that was pushed to a temporary location on the device. @@ -368,8 +369,9 @@ public async Task InstallPackageAsync(string packageFilePath, IProgressA which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install. /// A which represents the asynchronous operation. - public async Task InstallRemotePackageAsync(string remoteFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => - await InstallRemotePackageAsync(remoteFilePath, progress.AsAction(), cancellationToken, arguments).ConfigureAwait(false); + [MethodImpl((MethodImplOptions)0x100)] + public Task InstallRemotePackageAsync(string remoteFilePath, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + InstallRemotePackageAsync(remoteFilePath, progress.AsAction(), cancellationToken, arguments); /// /// Asynchronously installs Android multiple application on device. @@ -381,8 +383,9 @@ public async Task InstallRemotePackageAsync(string remoteFilePath, IProgressA which can be used to cancel the asynchronous operation. /// The arguments to pass to pm install-create. /// A which represents the asynchronous operation. - 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); + [MethodImpl((MethodImplOptions)0x100)] + public Task InstallMultiplePackageAsync(string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + InstallMultiplePackageAsync(basePackageFilePath, splitPackageFilePaths, progress.AsAction(), cancellationToken, arguments); /// /// Asynchronously installs Android multiple application on device. @@ -394,8 +397,9 @@ public async Task InstallMultiplePackageAsync(string basePackageFilePath, IEnume /// 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 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); + [MethodImpl((MethodImplOptions)0x100)] + public Task InstallMultiplePackageAsync(IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + InstallMultiplePackageAsync(splitPackageFilePaths, packageName, progress.AsAction(), cancellationToken, arguments); /// /// Asynchronously installs the multiple application package that was pushed to a temporary location on the device. @@ -407,8 +411,9 @@ public async Task InstallMultiplePackageAsync(IEnumerable splitPackageFi /// 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 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); + [MethodImpl((MethodImplOptions)0x100)] + public Task InstallMultipleRemotePackageAsync(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + InstallMultipleRemotePackageAsync(baseRemoteFilePath, splitRemoteFilePaths, progress.AsAction(), cancellationToken, arguments); /// /// Asynchronously installs the multiple application package that was pushed to a temporary location on the device. @@ -420,8 +425,9 @@ public async Task InstallMultipleRemotePackageAsync(string baseRemoteFilePath, I /// 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 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); + [MethodImpl((MethodImplOptions)0x100)] + public Task InstallMultipleRemotePackageAsync(IEnumerable splitRemoteFilePaths, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => + InstallMultipleRemotePackageAsync(splitRemoteFilePaths, packageName, progress.AsAction(), cancellationToken, arguments); #endif /// @@ -444,7 +450,7 @@ public async Task UninstallPackageAsync(string packageName, CancellationToken ca { ValidateDevice(); - DefaultInterpolatedStringHandler requestBuilder = new(13, (arguments?.Length ?? 0) + 1); + scoped DefaultInterpolatedStringHandler requestBuilder = new(13, (arguments?.Length ?? 0) + 1); requestBuilder.AppendLiteral("pm uninstall"); if (arguments != null) @@ -494,7 +500,7 @@ protected async Task CreateInstallSessionAsync(string? packageName = nul { ValidateDevice(); - DefaultInterpolatedStringHandler requestBuilder = new(21, (arguments?.Length ?? 0) + 1); + scoped DefaultInterpolatedStringHandler requestBuilder = new(21, (arguments?.Length ?? 0) + 1); requestBuilder.AppendLiteral("pm install-create"); if (!string.IsNullOrWhiteSpace(packageName)) diff --git a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs index b3668cb..56043e6 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/PackageManager.cs @@ -131,7 +131,7 @@ public void RefreshPackages() { ValidateDevice(); - DefaultInterpolatedStringHandler requestBuilder = new(19, Arguments?.Length ?? 0); + scoped DefaultInterpolatedStringHandler requestBuilder = new(19, Arguments?.Length ?? 0); requestBuilder.AppendLiteral(ListFull); if (Arguments != null) @@ -188,7 +188,7 @@ public void InstallRemotePackage(string remoteFilePath, Action splitRemoteFilePath /// 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. + [MethodImpl((MethodImplOptions)0x100)] public void InstallPackage(string packageFilePath, IProgress? progress = null, params string[] arguments) => InstallPackage(packageFilePath, progress.AsAction(), arguments); @@ -428,6 +429,7 @@ public 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. + [MethodImpl((MethodImplOptions)0x100)] public void InstallRemotePackage(string remoteFilePath, IProgress? progress = null, params string[] arguments) => InstallRemotePackage(remoteFilePath, progress.AsAction(), arguments); @@ -439,6 +441,7 @@ public 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. + [MethodImpl((MethodImplOptions)0x100)] public void InstallMultiplePackage(string basePackageFilePath, IEnumerable splitPackageFilePaths, IProgress? progress = null, params string[] arguments) => InstallMultiplePackage(basePackageFilePath, splitPackageFilePaths, progress.AsAction(), arguments); @@ -450,6 +453,7 @@ public void InstallMultiplePackage(string basePackageFilePath, IEnumerableAn 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. + [MethodImpl((MethodImplOptions)0x100)] public void InstallMultiplePackage(IEnumerable splitPackageFilePaths, string packageName, IProgress? progress = null, params string[] arguments) => InstallMultiplePackage(splitPackageFilePaths, packageName, progress.AsAction(), arguments); @@ -461,6 +465,7 @@ public void InstallMultiplePackage(IEnumerable splitPackageFilePaths, st /// 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. + [MethodImpl((MethodImplOptions)0x100)] public void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnumerable splitRemoteFilePaths, IProgress? progress = null, params string[] arguments) => InstallMultipleRemotePackage(baseRemoteFilePath, splitRemoteFilePaths, progress.AsAction(), arguments); @@ -472,6 +477,7 @@ public void InstallMultipleRemotePackage(string baseRemoteFilePath, IEnumerable< /// 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. + [MethodImpl((MethodImplOptions)0x100)] public void InstallMultipleRemotePackage(IEnumerable splitRemoteFilePaths, string packageName, IProgress? progress = null, params string[] arguments) => InstallMultipleRemotePackage(splitRemoteFilePaths, packageName, progress.AsAction(), arguments); #endif @@ -485,7 +491,7 @@ public void UninstallPackage(string packageName, params string[] arguments) { ValidateDevice(); - DefaultInterpolatedStringHandler requestBuilder = new(13, (arguments?.Length ?? 0) + 1); + scoped DefaultInterpolatedStringHandler requestBuilder = new(13, (arguments?.Length ?? 0) + 1); requestBuilder.AppendLiteral("pm uninstall"); if (arguments != null) @@ -536,7 +542,7 @@ protected string CreateInstallSession(string? packageName = null, params string[ { ValidateDevice(); - DefaultInterpolatedStringHandler requestBuilder = new(21, (arguments?.Length ?? 0) + 1); + scoped DefaultInterpolatedStringHandler requestBuilder = new(21, (arguments?.Length ?? 0) + 1); requestBuilder.AppendLiteral("pm install-create"); if (!string.IsNullOrWhiteSpace(packageName)) diff --git a/AdvancedSharpAdbClient/DeviceCommands/Receivers/VersionInfoReceiver.cs b/AdvancedSharpAdbClient/DeviceCommands/Receivers/VersionInfoReceiver.cs index fd78f2b..46b2962 100644 --- a/AdvancedSharpAdbClient/DeviceCommands/Receivers/VersionInfoReceiver.cs +++ b/AdvancedSharpAdbClient/DeviceCommands/Receivers/VersionInfoReceiver.cs @@ -92,7 +92,7 @@ private void CheckPackagesSection(string line) if (inPackagesSection && line != null) { #if HAS_BUFFERS - ReadOnlySpan span = line.AsSpan().Trim(); + scoped ReadOnlySpan span = line.AsSpan().Trim(); if (span.StartsWith("versionName=")) { return span[12..].Trim().ToString(); diff --git a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs index 1fa47ba..147e109 100644 --- a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs +++ b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.Async.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Net; +using System.Runtime.CompilerServices; using System.Text; using System.Threading; @@ -28,6 +29,7 @@ public partial class AdbClientExtensions /// A which represents the asynchronous operation. /// If your requested to start forwarding to local port TCP:0, the port number of the TCP port /// which has been opened. In all other cases, 0. + [MethodImpl((MethodImplOptions)0x100)] public static Task CreateForwardAsync(this IAdbClient client, DeviceData device, ForwardSpec local, ForwardSpec remote, bool allowRebind, CancellationToken cancellationToken = default) => client.CreateForwardAsync(device, local.ToString(), remote.ToString(), allowRebind, cancellationToken); @@ -43,6 +45,7 @@ public static Task CreateForwardAsync(this IAdbClient client, DeviceData de /// If your requested to start forwarding to local port TCP:0, the port number of the TCP port /// which has been opened. In all other cases, 0. /// Failed to submit the forward command. Or Device rejected command: + resp.Message. + [MethodImpl((MethodImplOptions)0x100)] public static Task CreateForwardAsync(this IAdbClient client, DeviceData device, int localPort, int remotePort, CancellationToken cancellationToken = default) => client.CreateForwardAsync(device, $"tcp:{localPort}", $"tcp:{remotePort}", true, cancellationToken); @@ -59,6 +62,7 @@ public static Task CreateForwardAsync(this IAdbClient client, DeviceData de /// which has been opened. In all other cases, 0. /// The client failed to submit the forward command. /// The device rejected command. The error message will include the error message provided by the device. + [MethodImpl((MethodImplOptions)0x100)] public static Task CreateForwardAsync(this IAdbClient client, DeviceData device, int localPort, string remoteSocket, CancellationToken cancellationToken = default) => client.CreateForwardAsync(device, $"tcp:{localPort}", $"local:{remoteSocket}", true, cancellationToken); @@ -76,6 +80,7 @@ public static Task CreateForwardAsync(this IAdbClient client, DeviceData de /// A which represents the asynchronous operation. /// If your requested to start reverse to remote port TCP:0, the port number of the TCP port /// which has been opened. In all other cases, 0. + [MethodImpl((MethodImplOptions)0x100)] public static Task CreateReverseForwardAsync(this IAdbClient client, DeviceData device, ForwardSpec remote, ForwardSpec local, bool allowRebind, CancellationToken cancellationToken = default) => client.CreateReverseForwardAsync(device, remote.ToString(), local.ToString(), allowRebind, cancellationToken); @@ -87,6 +92,7 @@ public static Task CreateReverseForwardAsync(this IAdbClient client, Device /// Specification of the remote that was forwarded /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task RemoveReverseForwardAsync(this IAdbClient client, DeviceData device, ForwardSpec remote, CancellationToken cancellationToken = default) => client.RemoveReverseForwardAsync(device, remote.ToString(), cancellationToken); @@ -100,6 +106,7 @@ public static Task RemoveReverseForwardAsync(this IAdbClient client, DeviceData /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteServerCommandAsync(this IAdbClient client, string target, string command, IShellOutputReceiver? receiver, CancellationToken cancellationToken = default) => client.ExecuteServerCommandAsync(target, command, receiver, AdbClient.Encoding, cancellationToken); @@ -114,6 +121,7 @@ public static Task ExecuteServerCommandAsync(this IAdbClient client, string targ /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteServerCommandAsync(this IAdbClient client, string target, string command, IAdbSocket socket, IShellOutputReceiver? receiver, CancellationToken cancellationToken = default) => client.ExecuteServerCommandAsync(target, command, socket, receiver, AdbClient.Encoding, cancellationToken); @@ -126,6 +134,7 @@ public static Task ExecuteServerCommandAsync(this IAdbClient client, string targ /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteRemoteCommandAsync(this IAdbClient client, string command, DeviceData device, IShellOutputReceiver? receiver, CancellationToken cancellationToken = default) => client.ExecuteRemoteCommandAsync(command, device, receiver, AdbClient.Encoding, cancellationToken); @@ -139,6 +148,7 @@ public static Task ExecuteRemoteCommandAsync(this IAdbClient client, string comm /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteServerCommandAsync(this IAdbClient client, string target, string command, Func? predicate, CancellationToken cancellationToken = default) => client.ExecuteServerCommandAsync(target, command, predicate.AsShellOutputReceiver(), AdbClient.Encoding, cancellationToken); @@ -153,6 +163,7 @@ public static Task ExecuteServerCommandAsync(this IAdbClient client, string targ /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteServerCommandAsync(this IAdbClient client, string target, string command, IAdbSocket socket, Func? predicate, CancellationToken cancellationToken = default) => client.ExecuteServerCommandAsync(target, command, socket, predicate.AsShellOutputReceiver(), AdbClient.Encoding, cancellationToken); @@ -165,6 +176,7 @@ public static Task ExecuteServerCommandAsync(this IAdbClient client, string targ /// Optionally, a that processes the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteRemoteCommandAsync(this IAdbClient client, string command, DeviceData device, Func? predicate, CancellationToken cancellationToken = default) => client.ExecuteRemoteCommandAsync(command, device, predicate.AsShellOutputReceiver(), AdbClient.Encoding, cancellationToken); @@ -179,6 +191,7 @@ public static Task ExecuteRemoteCommandAsync(this IAdbClient client, string comm /// The encoding to use when parsing the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteServerCommandAsync(this IAdbClient client, string target, string command, Func? predicate, Encoding encoding, CancellationToken cancellationToken = default) => client.ExecuteServerCommandAsync(target, command, predicate.AsShellOutputReceiver(), encoding, cancellationToken); @@ -194,6 +207,7 @@ public static Task ExecuteServerCommandAsync(this IAdbClient client, string targ /// The encoding to use when parsing the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteServerCommandAsync(this IAdbClient client, string target, string command, IAdbSocket socket, Func? predicate, Encoding encoding, CancellationToken cancellationToken = default) => client.ExecuteServerCommandAsync(target, command, socket, predicate.AsShellOutputReceiver(), encoding, cancellationToken); @@ -207,6 +221,7 @@ public static Task ExecuteServerCommandAsync(this IAdbClient client, string targ /// The encoding to use when parsing the command output. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task ExecuteRemoteCommandAsync(this IAdbClient client, string command, DeviceData device, Func? predicate, Encoding encoding, CancellationToken cancellationToken = default) => client.ExecuteRemoteCommandAsync(command, device, predicate.AsShellOutputReceiver(), encoding, cancellationToken); @@ -220,6 +235,7 @@ public static Task ExecuteRemoteCommandAsync(this IAdbClient client, string comm /// The command to execute. /// A which can be used to cancel the asynchronous operation. /// A of strings, each representing a line of output from the command. + [MethodImpl((MethodImplOptions)0x100)] public static IAsyncEnumerable ExecuteServerEnumerableAsync(this IAdbClient client, string target, string command, CancellationToken cancellationToken = default) => client.ExecuteServerEnumerableAsync(target, command, AdbClient.Encoding, cancellationToken); @@ -233,6 +249,7 @@ public static IAsyncEnumerable ExecuteServerEnumerableAsync(this IAdbCli /// The to send command. /// A which can be used to cancel the asynchronous operation. /// A of strings, each representing a line of output from the command. + [MethodImpl((MethodImplOptions)0x100)] public static IAsyncEnumerable ExecuteServerEnumerableAsync(this IAdbClient client, string target, string command, IAdbSocket socket, CancellationToken cancellationToken = default) => client.ExecuteServerEnumerableAsync(target, command, socket, AdbClient.Encoding, cancellationToken); @@ -244,6 +261,7 @@ public static IAsyncEnumerable ExecuteServerEnumerableAsync(this IAdbCli /// The device on which to run the command. /// A which can be used to cancel the asynchronous operation. /// A of strings, each representing a line of output from the command. + [MethodImpl((MethodImplOptions)0x100)] public static IAsyncEnumerable ExecuteRemoteEnumerableAsync(this IAdbClient client, string command, DeviceData device, CancellationToken cancellationToken = default) => client.ExecuteRemoteEnumerableAsync(command, device, AdbClient.Encoding, cancellationToken); @@ -254,6 +272,7 @@ public static IAsyncEnumerable ExecuteRemoteEnumerableAsync(this IAdbCli /// The device on which to run the event log service. /// Optionally, the names of the logs to receive. /// A which contains the log entries. + [MethodImpl((MethodImplOptions)0x100)] public static IAsyncEnumerable RunLogServiceAsync(this IAdbClient client, DeviceData device, params LogId[] logNames) => client.RunLogServiceAsync(device, default, logNames); #endif @@ -266,6 +285,7 @@ public static IAsyncEnumerable RunLogServiceAsync(this IAdbClient clie /// A callback which will receive the event log messages as they are received. /// Optionally, the names of the logs to receive. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, Action messageSink, params LogId[] logNames) => client.RunLogServiceAsync(device, messageSink, default, logNames); @@ -276,6 +296,7 @@ public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, /// The device. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task RebootAsync(this IAdbClient client, DeviceData device, CancellationToken cancellationToken = default) => client.RebootAsync(string.Empty, device, cancellationToken); /// @@ -286,6 +307,7 @@ public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, /// The pairing code. /// A which can be used to cancel the asynchronous operation. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task PairAsync(this IAdbClient client, IPAddress address, string code, CancellationToken cancellationToken = default) => address == null ? throw new ArgumentNullException(nameof(address)) @@ -299,6 +321,7 @@ public static Task PairAsync(this IAdbClient client, IPAddress address, /// The pairing code. /// A which can be used to cancel the asynchronous operation. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task PairAsync(this IAdbClient client, IPEndPoint endpoint, string code, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -312,6 +335,7 @@ public static Task PairAsync(this IAdbClient client, IPEndPoint endpoint /// The pairing code. /// A which can be used to cancel the asynchronous operation. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task PairAsync(this IAdbClient client, string host, string code, CancellationToken cancellationToken = default) => client.PairAsync(host, AdbClient.DefaultPort, code, cancellationToken); @@ -322,6 +346,7 @@ public static Task PairAsync(this IAdbClient client, string host, string /// The IP address of the remote device. /// A which can be used to cancel the asynchronous operation. /// A which returns the results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task ConnectAsync(this IAdbClient client, IPAddress address, CancellationToken cancellationToken = default) => address == null ? throw new ArgumentNullException(nameof(address)) @@ -334,6 +359,7 @@ public static Task ConnectAsync(this IAdbClient client, IPAddress addres /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static Task ConnectAsync(this IAdbClient client, IPEndPoint endpoint, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -346,6 +372,7 @@ public static Task ConnectAsync(this IAdbClient client, IPEndPoint endpo /// The host address of the remote device. /// A which can be used to cancel the asynchronous operation. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task ConnectAsync(this IAdbClient client, string host, CancellationToken cancellationToken = default) => client.ConnectAsync(host, AdbClient.DefaultPort, cancellationToken); @@ -356,6 +383,7 @@ public static Task ConnectAsync(this IAdbClient client, string host, Can /// The IP address of the remote device. /// A which can be used to cancel the asynchronous operation. /// A which returns the results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task DisconnectAsync(this IAdbClient client, IPAddress address, CancellationToken cancellationToken = default) => address == null ? throw new ArgumentNullException(nameof(address)) @@ -368,6 +396,7 @@ public static Task DisconnectAsync(this IAdbClient client, IPAddress add /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static Task DisconnectAsync(this IAdbClient client, IPEndPoint endpoint, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -380,6 +409,7 @@ public static Task DisconnectAsync(this IAdbClient client, IPEndPoint en /// The host address of the remote device. /// A which can be used to cancel the asynchronous operation. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task DisconnectAsync(this IAdbClient client, string host, CancellationToken cancellationToken = default) => client.DisconnectAsync(host, AdbClient.DefaultPort, cancellationToken); @@ -392,6 +422,7 @@ public static Task DisconnectAsync(this IAdbClient client, string host, /// A callback which will receive the event log messages as they are received. /// Optionally, the names of the logs to receive. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, IProgress progress, params LogId[] logNames) => client.RunLogServiceAsync(device, progress.Report, default, logNames); @@ -404,6 +435,7 @@ public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, /// A which can be used to cancel the asynchronous operation. /// Optionally, the names of the logs to receive. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, IProgress progress, CancellationToken cancellationToken, params LogId[] logNames) => client.RunLogServiceAsync(device, progress.Report, cancellationToken, logNames); @@ -418,6 +450,7 @@ public static Task RunLogServiceAsync(this IAdbClient client, DeviceData device, /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallAsync(this IAdbClient client, DeviceData device, Stream apk, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => client.InstallAsync(device, apk, progress.AsAction(), cancellationToken, arguments); @@ -433,6 +466,7 @@ public static Task InstallAsync(this IAdbClient client, DeviceData device, Strea /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install-create. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallMultipleAsync(this IAdbClient client, DeviceData device, Stream baseAPK, IEnumerable splitAPKs, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => client.InstallMultipleAsync(device, baseAPK, splitAPKs, progress.AsAction(), cancellationToken, arguments); @@ -448,6 +482,7 @@ public static Task InstallMultipleAsync(this IAdbClient client, DeviceData devic /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install-create. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallMultipleAsync(this IAdbClient client, DeviceData device, IEnumerable splitAPKs, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => client.InstallMultipleAsync(device, splitAPKs, packageName, progress.AsAction(), cancellationToken, arguments); @@ -463,6 +498,7 @@ public static Task InstallMultipleAsync(this IAdbClient client, DeviceData devic /// The progress is reported as a value between 0 and 100, representing the percentage of the apk which has been transferred. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] 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); @@ -474,6 +510,7 @@ public static Task InstallWriteAsync(this IAdbClient client, DeviceData device, /// The pairing code. /// A which can be used to cancel the asynchronous operation. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static Task PairAsync(this IAdbClient client, DnsEndPoint endpoint, string code, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -486,6 +523,7 @@ public static Task PairAsync(this IAdbClient client, DnsEndPoint endpoin /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static Task ConnectAsync(this IAdbClient client, DnsEndPoint endpoint, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -498,6 +536,7 @@ public static Task ConnectAsync(this IAdbClient client, DnsEndPoint endp /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static Task DisconnectAsync(this IAdbClient client, DnsEndPoint endpoint, CancellationToken cancellationToken = default) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -515,6 +554,7 @@ public static Task DisconnectAsync(this IAdbClient client, DnsEndPoint e /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallAsync(this IAdbClient.IWinRT client, DeviceData device, IRandomAccessStream apk, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => client.InstallAsync(device, apk, progress.AsAction(), cancellationToken, arguments); @@ -530,6 +570,7 @@ public static Task InstallAsync(this IAdbClient.IWinRT client, DeviceData device /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install-create. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallMultipleAsync(this IAdbClient.IWinRT client, DeviceData device, IRandomAccessStream baseAPK, IEnumerable splitAPKs, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => client.InstallMultipleAsync(device, baseAPK, splitAPKs, progress.AsAction(), cancellationToken, arguments); @@ -545,6 +586,7 @@ public static Task InstallMultipleAsync(this IAdbClient.IWinRT client, DeviceDat /// A which can be used to cancel the asynchronous operation. /// The arguments to pass to adb install-create. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallMultipleAsync(this IAdbClient.IWinRT client, DeviceData device, IEnumerable splitAPKs, string packageName, IProgress? progress = null, CancellationToken cancellationToken = default, params string[] arguments) => client.InstallMultipleAsync(device, splitAPKs, packageName, progress.AsAction(), cancellationToken, arguments); @@ -560,6 +602,7 @@ public static Task InstallMultipleAsync(this IAdbClient.IWinRT client, DeviceDat /// The progress is reported as a value between 0 and 100, representing the percentage of the apk which has been transferred. /// A which can be used to cancel the asynchronous operation. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallWriteAsync(this IAdbClient.IWinRT client, DeviceData device, IRandomAccessStream apk, string apkName, string session, IProgress? progress = null, CancellationToken cancellationToken = default) => client.InstallWriteAsync(device, apk, apkName, session, progress.AsAction(), cancellationToken); #endif @@ -573,6 +616,7 @@ public static Task InstallWriteAsync(this IAdbClient.IWinRT client, DeviceData d /// The device on which to install the application. /// The arguments to pass to adb install-create. /// A which returns the session ID + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallCreateAsync(this IAdbClient client, DeviceData device, params string[] arguments) => client.InstallCreateAsync(device, default, arguments); @@ -585,6 +629,7 @@ public static Task InstallCreateAsync(this IAdbClient client, DeviceData /// The package name of the baseAPK to install. /// The arguments to pass to adb install-create. /// A which returns the session ID + [MethodImpl((MethodImplOptions)0x100)] public static Task InstallCreateAsync(this IAdbClient client, DeviceData device, string packageName, params string[] arguments) => client.InstallCreateAsync(device, packageName, default, arguments); @@ -596,6 +641,7 @@ public static Task InstallCreateAsync(this IAdbClient client, DeviceData /// The name of the package to uninstall. /// The arguments to pass to adb uninstall. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task UninstallAsync(this IAdbClient client, DeviceData device, string packageName, params string[] arguments) => client.UninstallAsync(device, packageName, default, arguments); } diff --git a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs index dfbab01..cda264e 100644 --- a/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs +++ b/AdvancedSharpAdbClient/Extensions/AdbClientExtensions.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Net; +using System.Runtime.CompilerServices; using System.Text; namespace AdvancedSharpAdbClient @@ -27,6 +28,7 @@ public static partial class AdbClientExtensions /// connection from . /// If your requested to start forwarding to local port TCP:0, the port number of the TCP port /// which has been opened. In all other cases, 0. + [MethodImpl((MethodImplOptions)0x100)] public static int CreateForward(this IAdbClient client, DeviceData device, ForwardSpec local, ForwardSpec remote, bool allowRebind) => client.CreateForward(device, local.ToString(), remote.ToString(), allowRebind); @@ -40,6 +42,7 @@ public static int CreateForward(this IAdbClient client, DeviceData device, Forwa /// If your requested to start forwarding to local port TCP:0, the port number of the TCP port /// which has been opened. In all other cases, 0. /// Failed to submit the forward command. Or Device rejected command: + resp.Message. + [MethodImpl((MethodImplOptions)0x100)] public static int CreateForward(this IAdbClient client, DeviceData device, int localPort, int remotePort) => client.CreateForward(device, $"tcp:{localPort}", $"tcp:{remotePort}", true); @@ -54,6 +57,7 @@ public static int CreateForward(this IAdbClient client, DeviceData device, int l /// which has been opened. In all other cases, 0. /// The client failed to submit the forward command. /// The device rejected command. The error message will include the error message provided by the device. + [MethodImpl((MethodImplOptions)0x100)] public static int CreateForward(this IAdbClient client, DeviceData device, int localPort, string remoteSocket) => client.CreateForward(device, $"tcp:{localPort}", $"local:{remoteSocket}", true); @@ -69,6 +73,7 @@ public static int CreateForward(this IAdbClient client, DeviceData device, int l /// is already bound through a previous reverse command. /// If your requested to start reverse to remote port TCP:0, the port number of the TCP port /// which has been opened. In all other cases, 0. + [MethodImpl((MethodImplOptions)0x100)] public static int CreateReverseForward(this IAdbClient client, DeviceData device, ForwardSpec remote, ForwardSpec local, bool allowRebind) => client.CreateReverseForward(device, remote.ToString(), local.ToString(), allowRebind); @@ -78,6 +83,7 @@ public static int CreateReverseForward(this IAdbClient client, DeviceData device /// An instance of a class that implements the interface. /// The device on which to remove the reverse port forwarding /// Specification of the remote that was forwarded + [MethodImpl((MethodImplOptions)0x100)] public static void RemoveReverseForward(this IAdbClient client, DeviceData device, ForwardSpec remote) => client.RemoveReverseForward(device, remote.ToString()); @@ -89,6 +95,7 @@ public static void RemoveReverseForward(this IAdbClient client, DeviceData devic /// localreserved, localabstract, jdwp, track-jdwp, sync, reverse and so on. /// The command to execute. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteServerCommand(this IAdbClient client, string target, string command, IShellOutputReceiver? receiver) => client.ExecuteServerCommand(target, command, receiver, AdbClient.Encoding); @@ -101,6 +108,7 @@ public static void ExecuteServerCommand(this IAdbClient client, string target, s /// The command to execute. /// The to send command. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteServerCommand(this IAdbClient client, string target, string command, IAdbSocket socket, IShellOutputReceiver? receiver) => client.ExecuteServerCommand(target, command, socket, receiver, AdbClient.Encoding); @@ -111,6 +119,7 @@ public static void ExecuteServerCommand(this IAdbClient client, string target, s /// The command to execute. /// The device on which to run the command. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteRemoteCommand(this IAdbClient client, string command, DeviceData device, IShellOutputReceiver? receiver) => client.ExecuteRemoteCommand(command, device, receiver, AdbClient.Encoding); @@ -122,6 +131,7 @@ public static void ExecuteRemoteCommand(this IAdbClient client, string command, /// localreserved, localabstract, jdwp, track-jdwp, sync, reverse and so on. /// The command to execute. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteServerCommand(this IAdbClient client, string target, string command, Func? predicate) => client.ExecuteServerCommand(target, command, predicate.AsShellOutputReceiver(), AdbClient.Encoding); @@ -134,6 +144,7 @@ public static void ExecuteServerCommand(this IAdbClient client, string target, s /// The command to execute. /// The to send command. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteServerCommand(this IAdbClient client, string target, string command, IAdbSocket socket, Func? predicate) => client.ExecuteServerCommand(target, command, socket, predicate.AsShellOutputReceiver(), AdbClient.Encoding); @@ -144,6 +155,7 @@ public static void ExecuteServerCommand(this IAdbClient client, string target, s /// The command to execute. /// The device on which to run the command. /// Optionally, a that processes the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteRemoteCommand(this IAdbClient client, string command, DeviceData device, Func? predicate) => client.ExecuteRemoteCommand(command, device, predicate.AsShellOutputReceiver(), AdbClient.Encoding); @@ -156,6 +168,7 @@ public static void ExecuteRemoteCommand(this IAdbClient client, string command, /// The command to execute. /// Optionally, a that processes the command output. /// The encoding to use when parsing the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteServerCommand(this IAdbClient client, string target, string command, Func? predicate, Encoding encoding) => client.ExecuteServerCommand(target, command, predicate.AsShellOutputReceiver(), encoding); @@ -169,6 +182,7 @@ public static void ExecuteServerCommand(this IAdbClient client, string target, s /// The to send command. /// Optionally, a that processes the command output. /// The encoding to use when parsing the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteServerCommand(this IAdbClient client, string target, string command, IAdbSocket socket, Func? predicate, Encoding encoding) => client.ExecuteServerCommand(target, command, socket, predicate.AsShellOutputReceiver(), encoding); @@ -180,6 +194,7 @@ public static void ExecuteServerCommand(this IAdbClient client, string target, s /// The device on which to run the command. /// Optionally, a that processes the command output. /// The encoding to use when parsing the command output. + [MethodImpl((MethodImplOptions)0x100)] public static void ExecuteRemoteCommand(this IAdbClient client, string command, DeviceData device, Func? predicate, Encoding encoding) => client.ExecuteRemoteCommand(command, device, predicate.AsShellOutputReceiver(), encoding); @@ -191,6 +206,7 @@ public static void ExecuteRemoteCommand(this IAdbClient client, string command, /// localreserved, localabstract, jdwp, track-jdwp, sync, reverse and so on. /// The command to execute. /// A of strings, each representing a line of output from the command. + [MethodImpl((MethodImplOptions)0x100)] public static IEnumerable ExecuteServerEnumerable(this IAdbClient client, string target, string command) => client.ExecuteServerEnumerable(target, command, AdbClient.Encoding); @@ -203,6 +219,7 @@ public static IEnumerable ExecuteServerEnumerable(this IAdbClient client /// The command to execute. /// The to send command. /// A of strings, each representing a line of output from the command. + [MethodImpl((MethodImplOptions)0x100)] public static IEnumerable ExecuteServerEnumerable(this IAdbClient client, string target, string command, IAdbSocket socket) => client.ExecuteServerEnumerable(target, command, socket, AdbClient.Encoding); @@ -213,6 +230,7 @@ public static IEnumerable ExecuteServerEnumerable(this IAdbClient client /// The command to execute. /// The device on which to run the command. /// A of strings, each representing a line of output from the command. + [MethodImpl((MethodImplOptions)0x100)] public static IEnumerable ExecuteRemoteEnumerable(this IAdbClient client, string command, DeviceData device) => client.ExecuteRemoteEnumerable(command, device, AdbClient.Encoding); @@ -223,6 +241,7 @@ public static IEnumerable ExecuteRemoteEnumerable(this IAdbClient client /// The device on which to run the event log service. /// A callback which will receive the event log messages as they are received. /// Optionally, the names of the logs to receive. + [MethodImpl((MethodImplOptions)0x100)] public static void RunLogService(this IAdbClient client, DeviceData device, Action messageSink, params LogId[] logNames) => client.RunLogService(device, messageSink, false, logNames); @@ -231,6 +250,7 @@ public static void RunLogService(this IAdbClient client, DeviceData device, Acti /// /// An instance of a class that implements the interface. /// The device. + [MethodImpl((MethodImplOptions)0x100)] public static void Reboot(this IAdbClient client, DeviceData device) => client.Reboot(string.Empty, device); /// @@ -240,6 +260,7 @@ public static void RunLogService(this IAdbClient client, DeviceData device, Acti /// The IP address of the remote device. /// The pairing code. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Pair(this IAdbClient client, IPAddress address, string code) => address == null ? throw new ArgumentNullException(nameof(address)) @@ -252,6 +273,7 @@ public static string Pair(this IAdbClient client, IPAddress address, string code /// The DNS endpoint at which the adb server on the device is running. /// The pairing code. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Pair(this IAdbClient client, IPEndPoint endpoint, string code) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -264,6 +286,7 @@ public static string Pair(this IAdbClient client, IPEndPoint endpoint, string co /// The host address of the remote device. /// The pairing code. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Pair(this IAdbClient client, string host, string code) => client.Pair(host, AdbClient.DefaultPort, code); @@ -273,6 +296,7 @@ public static string Pair(this IAdbClient client, string host, string code) => /// An instance of a class that implements the interface. /// The IP address of the remote device. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Connect(this IAdbClient client, IPAddress address) => address == null ? throw new ArgumentNullException(nameof(address)) @@ -284,6 +308,7 @@ public static string Connect(this IAdbClient client, IPAddress address) => /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static string Connect(this IAdbClient client, IPEndPoint endpoint) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -295,6 +320,7 @@ public static string Connect(this IAdbClient client, IPEndPoint endpoint) => /// An instance of a class that implements the interface. /// The host address of the remote device. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Connect(this IAdbClient client, string host) => client.Connect(host, AdbClient.DefaultPort); @@ -304,6 +330,7 @@ public static string Connect(this IAdbClient client, string host) => /// An instance of a class that implements the interface. /// The IP address of the remote device. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Disconnect(this IAdbClient client, IPAddress address) => address == null ? throw new ArgumentNullException(nameof(address)) @@ -315,6 +342,7 @@ public static string Disconnect(this IAdbClient client, IPAddress address) => /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static string Disconnect(this IAdbClient client, IPEndPoint endpoint) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -326,6 +354,7 @@ public static string Disconnect(this IAdbClient client, IPEndPoint endpoint) => /// An instance of a class that implements the interface. /// The host address of the remote device. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Disconnect(this IAdbClient client, string host) => client.Disconnect(host, AdbClient.DefaultPort); @@ -335,6 +364,7 @@ public static string Disconnect(this IAdbClient client, string host) => /// An instance of a class that implements the interface. /// The device on which to process command. /// A new instance of the class. + [MethodImpl((MethodImplOptions)0x100)] public static DeviceClient CreateDeviceClient(this IAdbClient client, DeviceData device) => new(client, device); /// @@ -344,6 +374,7 @@ public static string Disconnect(this IAdbClient client, string host) => /// The device on which to look for packages. /// The arguments to pass to pm list packages. /// A new instance of the class. + [MethodImpl((MethodImplOptions)0x100)] public static PackageManager CreatePackageManager(this IAdbClient client, DeviceData device, params string[] arguments) => new(client, device, arguments); #if !NETFRAMEWORK || NET40_OR_GREATER @@ -354,6 +385,7 @@ public static string Disconnect(this IAdbClient client, string host) => /// The device on which to run the event log service. /// A callback which will receive the event log messages as they are received. /// Optionally, the names of the logs to receive. + [MethodImpl((MethodImplOptions)0x100)] public static void RunLogService(this IAdbClient client, DeviceData device, IProgress progress, params LogId[] logNames) => client.RunLogService(device, progress, false, logNames); @@ -365,7 +397,8 @@ public static void RunLogService(this IAdbClient client, DeviceData device, IPro /// A callback which will receive the event log messages as they are received. /// A that can be used to cancel the task. /// Optionally, the names of the logs to receive. - public static void RunLogService(this IAdbClient client, DeviceData device, IProgress progress, in bool isCancelled, params LogId[] logNames) => + [MethodImpl((MethodImplOptions)0x100)] + public static void RunLogService(this IAdbClient client, DeviceData device, IProgress progress, scoped in bool isCancelled, params LogId[] logNames) => client.RunLogService(device, progress.Report, isCancelled, logNames); /// @@ -377,6 +410,7 @@ public static void RunLogService(this IAdbClient client, DeviceData device, IPro /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static void Install(this IAdbClient client, DeviceData device, Stream apk, IProgress? progress = null, params string[] arguments) => client.Install(device, apk, progress.AsAction(), arguments); @@ -390,6 +424,7 @@ public static void Install(this IAdbClient client, DeviceData device, Stream apk /// 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-create. + [MethodImpl((MethodImplOptions)0x100)] public static void InstallMultiple(this IAdbClient client, DeviceData device, Stream baseAPK, IEnumerable splitAPKs, IProgress? progress = null, params string[] arguments) => client.InstallMultiple(device, baseAPK, splitAPKs, progress.AsAction(), arguments); @@ -403,6 +438,7 @@ public static void InstallMultiple(this IAdbClient client, DeviceData device, St /// 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-create. + [MethodImpl((MethodImplOptions)0x100)] public static void InstallMultiple(this IAdbClient client, DeviceData device, IEnumerable splitAPKs, string packageName, IProgress? progress = null, params string[] arguments) => client.InstallMultiple(device, splitAPKs, packageName, progress.AsAction(), arguments); @@ -416,6 +452,7 @@ public static void InstallMultiple(this IAdbClient client, DeviceData device, IE /// The session ID of the install session. /// An optional parameter which, when specified, returns progress notifications. /// The progress is reported as a value between 0 and 100, representing the percentage of the apk which has been transferred. + [MethodImpl((MethodImplOptions)0x100)] 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()); @@ -426,6 +463,7 @@ public static void InstallWrite(this IAdbClient client, DeviceData device, Strea /// The DNS endpoint at which the adb server on the device is running. /// The pairing code. /// The results from adb. + [MethodImpl((MethodImplOptions)0x100)] public static string Pair(this IAdbClient client, DnsEndPoint endpoint, string code) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -437,6 +475,7 @@ public static string Pair(this IAdbClient client, DnsEndPoint endpoint, string c /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static string Connect(this IAdbClient client, DnsEndPoint endpoint) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) @@ -448,6 +487,7 @@ public static string Connect(this IAdbClient client, DnsEndPoint endpoint) => /// 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. + [MethodImpl((MethodImplOptions)0x100)] public static string Disconnect(this IAdbClient client, DnsEndPoint endpoint) => endpoint == null ? throw new ArgumentNullException(nameof(endpoint)) diff --git a/AdvancedSharpAdbClient/Extensions/EnumerableBuilder.cs b/AdvancedSharpAdbClient/Extensions/EnumerableBuilder.cs index d6e934d..45eebcc 100644 --- a/AdvancedSharpAdbClient/Extensions/EnumerableBuilder.cs +++ b/AdvancedSharpAdbClient/Extensions/EnumerableBuilder.cs @@ -23,7 +23,8 @@ public static class EnumerableBuilder /// /// The data that feeds the struct. /// A new instance of struct. - public static AdbCommandLineStatus AdbCommandLineStatusCreator(params ReadOnlySpan values) => + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AdbCommandLineStatus AdbCommandLineStatusCreator(params scoped ReadOnlySpan values) => AdbCommandLineStatus.GetVersionFromOutput(values); /// @@ -31,42 +32,47 @@ public static AdbCommandLineStatus AdbCommandLineStatusCreator(params ReadOnlySp /// /// The data that feeds the struct. /// A new instance of struct. - public static unsafe ColorData ColorDataCreator(ReadOnlySpan values) => Unsafe.As(ref MemoryMarshal.GetReference(values)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ColorData ColorDataCreator(scoped ReadOnlySpan values) => Unsafe.As(ref MemoryMarshal.GetReference(values)); /// /// Build a struct. /// /// The data that feeds the struct. /// A new instance of struct. - public static FramebufferHeader FramebufferHeaderCreator(ReadOnlySpan values) => new(values); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FramebufferHeader FramebufferHeaderCreator(scoped ReadOnlySpan values) => new(values); /// /// Build a struct. /// /// The data that feeds the struct. /// A new instance of struct. - public static unsafe FileStatisticsData FileStatisticsDataCreator(ReadOnlySpan values) => Unsafe.As(ref MemoryMarshal.GetReference(values)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FileStatisticsData FileStatisticsDataCreator(scoped ReadOnlySpan values) => Unsafe.As(ref MemoryMarshal.GetReference(values)); /// /// Build a struct. /// /// The data that feeds the struct. /// A new instance of struct. - public static unsafe FileStatisticsDataEx FileStatisticsDataV2Creator(ReadOnlySpan values) => Unsafe.As(ref MemoryMarshal.GetReference(values)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static FileStatisticsDataEx FileStatisticsDataV2Creator(scoped ReadOnlySpan values) => Unsafe.As(ref MemoryMarshal.GetReference(values)); /// /// Build a enum. /// /// The data that feeds the struct. /// A new instance of struct. - public static unsafe UnixFileStatus UnixFileStatusCreator(ReadOnlySpan values) => (UnixFileStatus)BitConverter.ToUInt32(values); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static UnixFileStatus UnixFileStatusCreator(scoped ReadOnlySpan values) => (UnixFileStatus)BitConverter.ToUInt32(values); /// /// Build a class. /// /// The data that feeds the struct. /// A new instance of struct. - public static LogEntry? LogEntryCreator(ReadOnlySpan values) + public static LogEntry? LogEntryCreator(scoped ReadOnlySpan values) { if (values.IsEmpty) { return null; } int index = 0; @@ -140,7 +146,7 @@ public static AdbCommandLineStatus AdbCommandLineStatusCreator(params ReadOnlySp } } - ReadOnlySpan data = ReadBytesSafe(values, payloadLength); + scoped ReadOnlySpan data = ReadBytesSafe(values, payloadLength); if (data.IsEmpty) { @@ -269,25 +275,25 @@ static void ReadLogEntry(BinaryReader reader, params ICollection parent) } } - ushort? ReadUInt16(in ReadOnlySpan bytes) + ushort? ReadUInt16(scoped in ReadOnlySpan bytes) { - ReadOnlySpan data = ReadBytesSafe(bytes, 2); + scoped ReadOnlySpan data = ReadBytesSafe(bytes, 2); return data.IsEmpty ? null : BitConverter.ToUInt16(data); } - uint? ReadUInt32(in ReadOnlySpan bytes) + uint? ReadUInt32(scoped in ReadOnlySpan bytes) { - ReadOnlySpan data = ReadBytesSafe(bytes, 4); + scoped ReadOnlySpan data = ReadBytesSafe(bytes, 4); return data.IsEmpty ? null : BitConverter.ToUInt32(data); } - int? ReadInt32(in ReadOnlySpan bytes) + int? ReadInt32(scoped in ReadOnlySpan bytes) { - ReadOnlySpan data = ReadBytesSafe(bytes, 4); + scoped ReadOnlySpan data = ReadBytesSafe(bytes, 4); return data.Length != 4 ? null : BitConverter.ToInt32(data); } - ReadOnlySpan ReadBytesSafe(in ReadOnlySpan bytes, int count) + ReadOnlySpan ReadBytesSafe(scoped in ReadOnlySpan bytes, int count) { if (bytes.Length < index + count) { return null; } ReadOnlySpan data = bytes.Slice(index, count); diff --git a/AdvancedSharpAdbClient/Extensions/Extensions.cs b/AdvancedSharpAdbClient/Extensions/Extensions.cs index 2e74777..723ee73 100644 --- a/AdvancedSharpAdbClient/Extensions/Extensions.cs +++ b/AdvancedSharpAdbClient/Extensions/Extensions.cs @@ -50,9 +50,10 @@ public static DnsEndPoint CreateDnsEndPoint(string host, int port) /// /// The function to call for each line of output /// The created from the specified function. + [MethodImpl((MethodImplOptions)0x100)] [return: NotNullIfNotNull(nameof(predicate))] public static IShellOutputReceiver? AsShellOutputReceiver(this Func? predicate) => - predicate == null ? null! : new FunctionOutputReceiver(predicate); + predicate == null ? null : new FunctionOutputReceiver(predicate); #if HAS_TASK #if !NET7_0_OR_GREATER @@ -107,12 +108,14 @@ public static Task ReadToEndAsync(this TextReader reader, CancellationTo /// Closes the connection and releases all associated resources. /// /// The to release. + [MethodImpl((MethodImplOptions)0x100)] public static void Close(this Socket socket) => socket.Dispose(); /// /// Closes the and releases any system resources associated with the . /// /// The to release. + [MethodImpl((MethodImplOptions)0x100)] public static void Close(this TextReader reader) => reader.Dispose(); #else #if HAS_TASK && !NET5_0_OR_GREATER @@ -124,6 +127,7 @@ public static Task ReadToEndAsync(this TextReader reader, CancellationTo /// An optional token to cancel the asynchronous operation. /// A task that will complete when the process has exited, cancellation has been requested, /// or an error occurs. + [MethodImpl((MethodImplOptions)0x100)] public static Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default) => Task.Run(process.WaitForExit, cancellationToken); #endif @@ -156,9 +160,9 @@ public static void Dispose(this WaitHandle waitHandle) /// The type of progress update value. /// The to convert. /// The created from the specified . + [MethodImpl((MethodImplOptions)0x100)] [return: NotNullIfNotNull(nameof(progress))] - public static Action? AsAction(this IProgress? progress) => - progress == null ? null : progress.Report; + public static Action? AsAction(this IProgress? progress) => progress == null ? null : progress.Report; #endif #if HAS_WINRT @@ -183,6 +187,7 @@ public static string GetFullPath(string path) => /// /// The socket to use. /// The request to send. + [MethodImpl((MethodImplOptions)0x100)] public static void SendAdbRequest(this IAdbSocket socket, scoped in DefaultInterpolatedStringHandler request) => socket.SendAdbRequest(request.ToString()); } } diff --git a/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs b/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs index 0a39c61..807c200 100644 --- a/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs +++ b/AdvancedSharpAdbClient/Extensions/LoggerExtensions.cs @@ -3,6 +3,8 @@ // using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; namespace AdvancedSharpAdbClient.Logs { @@ -21,7 +23,8 @@ public static class LoggerExtensions /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogDebug(exception, "Error while processing request from {Address}", address) - public static void LogDebug(this ILogger logger, Exception? exception, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogDebug(this ILogger logger, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Debug, exception, message, args); /// @@ -31,7 +34,8 @@ public static void LogDebug(this ILogger logger, Exception? exception, string? m /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogDebug("Processing request from {Address}", address) - public static void LogDebug(this ILogger logger, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogDebug(this ILogger logger, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Debug, message, args); //------------------------------------------TRACE------------------------------------------// @@ -44,7 +48,8 @@ public static void LogDebug(this ILogger logger, string? message, params object? /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogTrace(exception, "Error while processing request from {Address}", address) - public static void LogTrace(this ILogger logger, Exception? exception, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogTrace(this ILogger logger, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Trace, exception, message, args); /// @@ -54,7 +59,8 @@ public static void LogTrace(this ILogger logger, Exception? exception, string? m /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogTrace("Processing request from {Address}", address) - public static void LogTrace(this ILogger logger, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogTrace(this ILogger logger, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Trace, message, args); //------------------------------------------INFORMATION------------------------------------------// @@ -67,7 +73,8 @@ public static void LogTrace(this ILogger logger, string? message, params object? /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogInformation(exception, "Error while processing request from {Address}", address) - public static void LogInformation(this ILogger logger, Exception? exception, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogInformation(this ILogger logger, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Information, exception, message, args); /// @@ -77,7 +84,8 @@ public static void LogInformation(this ILogger logger, Exception? exception, str /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogInformation("Processing request from {Address}", address) - public static void LogInformation(this ILogger logger, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogInformation(this ILogger logger, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Information, message, args); //------------------------------------------WARNING------------------------------------------// @@ -90,7 +98,8 @@ public static void LogInformation(this ILogger logger, string? message, params o /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogWarning(exception, "Error while processing request from {Address}", address) - public static void LogWarning(this ILogger logger, Exception? exception, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogWarning(this ILogger logger, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Warning, exception, message, args); /// @@ -100,7 +109,8 @@ public static void LogWarning(this ILogger logger, Exception? exception, string? /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogWarning("Processing request from {Address}", address) - public static void LogWarning(this ILogger logger, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogWarning(this ILogger logger, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Warning, message, args); //------------------------------------------ERROR------------------------------------------// @@ -113,7 +123,8 @@ public static void LogWarning(this ILogger logger, string? message, params objec /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogError(exception, "Error while processing request from {Address}", address) - public static void LogError(this ILogger logger, Exception? exception, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogError(this ILogger logger, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Error, exception, message, args); /// @@ -123,7 +134,8 @@ public static void LogError(this ILogger logger, Exception? exception, string? m /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogError("Processing request from {Address}", address) - public static void LogError(this ILogger logger, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogError(this ILogger logger, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Error, message, args); //------------------------------------------CRITICAL------------------------------------------// @@ -136,7 +148,8 @@ public static void LogError(this ILogger logger, string? message, params object? /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogCritical(exception, "Error while processing request from {Address}", address) - public static void LogCritical(this ILogger logger, Exception? exception, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogCritical(this ILogger logger, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Critical, exception, message, args); /// @@ -146,7 +159,8 @@ public static void LogCritical(this ILogger logger, Exception? exception, string /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogCritical("Processing request from {Address}", address) - public static void LogCritical(this ILogger logger, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void LogCritical(this ILogger logger, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(LogLevel.Critical, message, args); /// @@ -156,7 +170,8 @@ public static void LogCritical(this ILogger logger, string? message, params obje /// Entry will be written on this level. /// Format string of the log message. /// An object array that contains zero or more objects to format. - public static void Log(this ILogger logger, LogLevel logLevel, string? message, params object?[] args) => + [MethodImpl((MethodImplOptions)0x100)] + public static void Log(this ILogger logger, LogLevel logLevel, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) => logger.Log(logLevel, null, message, args); } } \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Extensions/SyncCommandConverter.cs b/AdvancedSharpAdbClient/Extensions/SyncCommandConverter.cs index 95a8480..4271f81 100644 --- a/AdvancedSharpAdbClient/Extensions/SyncCommandConverter.cs +++ b/AdvancedSharpAdbClient/Extensions/SyncCommandConverter.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace AdvancedSharpAdbClient.Models { @@ -22,12 +23,14 @@ public static class SyncCommandConverter /// Gets the byte array that represents the . /// /// A byte array that represents the . + [MethodImpl((MethodImplOptions)0x100)] public byte[] GetBytes() => BitConverter.GetBytes((int)command); /// /// Returns an enumerator that iterates through the . /// /// An enumerator that can be used to iterate through the . + [MethodImpl((MethodImplOptions)0x100)] public IEnumerator GetEnumerator() => ((IEnumerable)command.GetBytes()).GetEnumerator(); /// @@ -38,7 +41,6 @@ public static class SyncCommandConverter public static SyncCommand GetCommand(byte[] value) { ArgumentNullException.ThrowIfNull(value); - return value.Length != 4 ? throw new ArgumentOutOfRangeException(nameof(value)) : (SyncCommand)BitConverter.ToInt32(value); } @@ -48,10 +50,8 @@ public static SyncCommand GetCommand(byte[] value) /// /// A byte array that represents a . /// The corresponding . - public static SyncCommand GetCommand(ReadOnlySpan value) - { - return value.Length != 4 ? throw new ArgumentOutOfRangeException(nameof(value)) : (SyncCommand)BitConverter.ToInt32(value); - } + public static SyncCommand GetCommand(scoped ReadOnlySpan value) => + value.Length != 4 ? throw new ArgumentOutOfRangeException(nameof(value)) : (SyncCommand)BitConverter.ToInt32(value); #endif } } diff --git a/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.Async.cs b/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.Async.cs index e46c136..5b21052 100644 --- a/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.Async.cs +++ b/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.Async.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading; namespace AdvancedSharpAdbClient @@ -22,6 +23,7 @@ public static partial class SyncServiceExtensions /// A that can be used to cancel the task. /// A which returns a object that contains information about the file. /// File size bigger than 4GB need V2, and V2 need Android 8 or above. + [MethodImpl((MethodImplOptions)0x100)] public static Task StatAsync(this ISyncService service, string remotePath, bool useV2 = false, CancellationToken cancellationToken = default) => useV2 ? service.StatExAsync(remotePath, cancellationToken).ContinueWith(x => x.Result as IFileStatistics) : service.StatAsync(remotePath, cancellationToken).ContinueWith(x => x.Result as IFileStatistics); @@ -34,6 +36,7 @@ public static Task StatAsync(this ISyncService service, string /// A that can be used to cancel the task. /// A which returns for each child item of the directory, a object with information of the item. /// File size bigger than 4GB need V2, and V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static Task> GetDirectoryListingAsync(this ISyncService service, string remotePath, bool useV2 = false, CancellationToken cancellationToken = default) => #if NETFRAMEWORK && !NET40_OR_GREATER useV2 ? service.GetDirectoryListingExAsync(remotePath, cancellationToken).ContinueWith(x => x.Result.OfType()) : service.GetDirectoryListingAsync(remotePath, cancellationToken).ContinueWith(x => x.Result.OfType()); @@ -51,6 +54,7 @@ public static Task> GetDirectoryListingAsync(this I /// A that can be used to cancel the task. /// An which returns for each child item of the directory, a object with information of the item. /// File size bigger than 4GB need V2, and V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static IAsyncEnumerable GetDirectoryAsyncListing(this ISyncService service, string remotePath, bool useV2 = false, CancellationToken cancellationToken = default) => useV2 ? service.GetDirectoryAsyncListingEx(remotePath, cancellationToken) : service.GetDirectoryAsyncListing(remotePath, cancellationToken); #endif @@ -68,6 +72,7 @@ public static IAsyncEnumerable GetDirectoryAsyncListing(this IS /// to use ; otherwise, use . /// A that can be used to cancel the task. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task PushAsync(this ISyncService service, Stream stream, string remotePath, UnixFileStatus permissions, DateTimeOffset timestamp, IProgress? progress = null, bool useV2 = false, CancellationToken cancellationToken = default) => service.PushAsync(stream, remotePath, permissions, timestamp, progress.AsAction(), useV2, cancellationToken); @@ -82,6 +87,7 @@ public static Task PushAsync(this ISyncService service, Stream stream, string re /// A that can be used to cancel the task. /// A which represents the asynchronous operation. /// File size bigger than 4GB need V2, and V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static Task PullAsync(this ISyncService service, string remotePath, Stream stream, IProgress? progress = null, bool useV2 = false, CancellationToken cancellationToken = default) => service.PullAsync(remotePath, stream, progress.AsAction(), useV2, cancellationToken); @@ -98,6 +104,7 @@ public static Task PullAsync(this ISyncService service, string remotePath, Strea /// to use ; otherwise, use . /// A that can be used to cancel the task. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task PushAsync(this ISyncService.IWinRT service, IInputStream stream, string remotePath, UnixFileStatus permissions, DateTimeOffset timestamp, IProgress? progress = null, bool useV2 = false, CancellationToken cancellationToken = default) => service.PushAsync(stream, remotePath, permissions, timestamp, progress.AsAction(), useV2, cancellationToken); @@ -112,6 +119,7 @@ public static Task PushAsync(this ISyncService.IWinRT service, IInputStream stre /// A that can be used to cancel the task. /// A which represents the asynchronous operation. /// File size bigger than 4GB need V2, and V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static Task PullAsync(this ISyncService.IWinRT service, string remotePath, IOutputStream stream, IProgress? progress = null, bool useV2 = false, CancellationToken cancellationToken = default) => service.PullAsync(remotePath, stream, progress.AsAction(), useV2, cancellationToken); #endif @@ -129,6 +137,7 @@ public static Task PullAsync(this ISyncService.IWinRT service, string remotePath /// to use ; otherwise, use . /// A that can be used to cancel the task. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task PushAsync(this ISyncService service, Stream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, CancellationToken cancellationToken = default) => service.PushAsync(stream, remotePath, (UnixFileStatus)permissions, timestamp, callback, useV2, cancellationToken); @@ -144,6 +153,7 @@ public static Task PushAsync(this ISyncService service, Stream stream, string re /// to use ; otherwise, use . /// A that can be used to cancel the task. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task PushAsync(this ISyncService service, Stream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, IProgress? progress, bool useV2 = false, CancellationToken cancellationToken = default) => service.PushAsync(stream, remotePath, (UnixFileStatus)permissions, timestamp, progress.AsAction(), useV2, cancellationToken); @@ -160,6 +170,7 @@ public static Task PushAsync(this ISyncService service, Stream stream, string re /// to use ; otherwise, use . /// A that can be used to cancel the task. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task PushAsync(this ISyncService.IWinRT service, IInputStream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, CancellationToken cancellationToken = default) => service.PushAsync(stream, remotePath, (UnixFileStatus)permissions, timestamp, callback, useV2, cancellationToken); @@ -175,6 +186,7 @@ public static Task PushAsync(this ISyncService.IWinRT service, IInputStream stre /// to use ; otherwise, use . /// A that can be used to cancel the task. /// A which represents the asynchronous operation. + [MethodImpl((MethodImplOptions)0x100)] public static Task PushAsync(this ISyncService.IWinRT service, IInputStream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, IProgress? progress, bool useV2 = false, CancellationToken cancellationToken = default) => service.PushAsync(stream, remotePath, (UnixFileStatus)permissions, timestamp, progress.AsAction(), useV2, cancellationToken); #endif diff --git a/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.cs b/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.cs index 48e1f9d..7b64bd5 100644 --- a/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.cs +++ b/AdvancedSharpAdbClient/Extensions/SyncServiceExtensions.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; namespace AdvancedSharpAdbClient { @@ -22,6 +23,7 @@ public static partial class SyncServiceExtensions /// to use ; otherwise, use . /// A object that contains information about the file. /// File size bigger than 4GB need V2, and V2 need Android 8 or above. + [MethodImpl((MethodImplOptions)0x100)] public static IFileStatistics Stat(this ISyncService service, string remotePath, bool useV2 = false) => useV2 ? service.StatEx(remotePath) : service.Stat(remotePath); @@ -33,6 +35,7 @@ public static IFileStatistics Stat(this ISyncService service, string remotePath, /// to use ; otherwise, use . /// For each child item of the directory, a object with information of the item. /// V2 need Android 11 or above. + [MethodImpl((MethodImplOptions)0x100)] public static IEnumerable GetDirectoryListing(this ISyncService service, string remotePath, bool useV2 = false) => #if NETFRAMEWORK && !NET40_OR_GREATER useV2 ? service.GetDirectoryListingEx(remotePath).OfType() : service.GetDirectoryListing(remotePath).OfType(); @@ -53,7 +56,8 @@ public static IEnumerable GetDirectoryListing(this ISyncService /// to use ; otherwise, use . /// A that can be used to cancel the task. /// V2 need Android 11 or above. - public static void Push(this ISyncService service, Stream stream, string remotePath, UnixFileStatus permissions, DateTimeOffset timestamp, IProgress? progress = null, bool useV2 = false, in bool isCancelled = false) => + [MethodImpl((MethodImplOptions)0x100)] + public static void Push(this ISyncService service, Stream stream, string remotePath, UnixFileStatus permissions, DateTimeOffset timestamp, IProgress? progress = null, bool useV2 = false, scoped in bool isCancelled = false) => service.Push(stream, remotePath, permissions, timestamp, progress.AsAction(), useV2, isCancelled); /// @@ -66,7 +70,8 @@ public static void Push(this ISyncService service, Stream stream, string remoteP /// to use and ; otherwise, use and . /// A that can be used to cancel the task. /// File size bigger than 4GB need V2, and V2 need Android 11 or above. - public static void Pull(this ISyncService service, string remotePath, Stream stream, IProgress? progress = null, bool useV2 = false, in bool isCancelled = false) => + [MethodImpl((MethodImplOptions)0x100)] + public static void Pull(this ISyncService service, string remotePath, Stream stream, IProgress? progress = null, bool useV2 = false, scoped in bool isCancelled = false) => service.Pull(remotePath, stream, progress.AsAction(), useV2, isCancelled); #if NET7_0_OR_GREATER @@ -82,7 +87,8 @@ public static void Pull(this ISyncService service, string remotePath, Stream str /// to use ; otherwise, use . /// A that can be used to cancel the task. /// V2 need Android 11 or above. - public static void Push(this ISyncService service, Stream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, in bool isCancelled = false) => + [MethodImpl((MethodImplOptions)0x100)] + public static void Push(this ISyncService service, Stream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, scoped in bool isCancelled = false) => service.Push(stream, remotePath, (UnixFileStatus)permissions, timestamp, callback, useV2, isCancelled); /// @@ -97,7 +103,8 @@ public static void Push(this ISyncService service, Stream stream, string remoteP /// to use ; otherwise, use . /// A that can be used to cancel the task. /// V2 need Android 11 or above. - public static void Push(this ISyncService service, Stream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, IProgress? progress, bool useV2 = false, in bool isCancelled = false) => + [MethodImpl((MethodImplOptions)0x100)] + public static void Push(this ISyncService service, Stream stream, string remotePath, UnixFileMode permissions, DateTimeOffset timestamp, IProgress? progress, bool useV2 = false, scoped in bool isCancelled = false) => service.Push(stream, remotePath, (UnixFileStatus)permissions, timestamp, progress.AsAction(), useV2, isCancelled); #endif #endif diff --git a/AdvancedSharpAdbClient/Extensions/UnixFileStatusExtensions.cs b/AdvancedSharpAdbClient/Extensions/UnixFileStatusExtensions.cs index 6a50d97..59b5e4e 100644 --- a/AdvancedSharpAdbClient/Extensions/UnixFileStatusExtensions.cs +++ b/AdvancedSharpAdbClient/Extensions/UnixFileStatusExtensions.cs @@ -8,6 +8,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace AdvancedSharpAdbClient.Models { @@ -26,24 +27,28 @@ public static class UnixFileStatusExtensions /// Gets the type of the given file status. /// /// The type of the file status. + [MethodImpl((MethodImplOptions)0x100)] public UnixFileStatus GetFileType() => mode & UnixFileStatus.TypeMask; /// /// Gets the permissions of the given file status. /// /// The permissions of the given file status. + [MethodImpl((MethodImplOptions)0x100)] public UnixFileStatus GetPermissions() => mode & UnixFileStatus.AllPermissions; /// /// Gets the access permissions of the given file status. /// /// The access permissions of the given file status. + [MethodImpl((MethodImplOptions)0x100)] public UnixFileStatus GetAccessPermissions() => mode & UnixFileStatus.AccessPermissions; /// /// Checks if the given file status corresponds to a directory, as if determined by . /// /// if the type indicated refers to a directory, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsDirectory() => mode.GetFileType() == UnixFileStatus.Directory; /// @@ -51,6 +56,7 @@ public static class UnixFileStatusExtensions /// Examples of character special files are character devices such as /dev/null, /dev/tty, /dev/audio, or /dev/nvram on Linux. /// /// if the type indicated refers to a character device, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsCharacterFile() => mode.GetFileType() == UnixFileStatus.Character; /// @@ -58,42 +64,49 @@ public static class UnixFileStatusExtensions /// Examples of block special files are block devices such as /dev/sda or /dev/loop0 on Linux. /// /// if the type indicated refers to a block device, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsBlockFile() => mode.GetFileType() == UnixFileStatus.Block; /// /// Checks if the given file status corresponds to a regular file, as if determined by . /// /// if the type indicated by refers to a regular file, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsRegularFile() => mode.GetFileType() == UnixFileStatus.Regular; /// /// Checks if the given file status corresponds to a FIFO or pipe file as if determined by . /// /// if the type indicated refers to a FIFO pipe, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsFIFO() => mode.GetFileType() == UnixFileStatus.FIFO; /// /// Checks if the given file status corresponds to a symbolic link, as if determined by . /// /// if the type indicated refers to a symbolic link, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsSymbolicLink() => mode.GetFileType() == UnixFileStatus.SymbolicLink; /// /// Checks if the given file status or path corresponds to a named IPC socket, as if determined by . /// /// if the type indicated refers to a named socket, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsSocket() => mode.GetFileType() == UnixFileStatus.Socket; /// /// Checks if the given file status corresponds to a file of type other type. That is, the file exists, but is neither regular file, nor directory nor a symlink. /// /// if the type indicated refers to a file that is not regular file, directory, or a symlink, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsOther() => mode.GetFileType() is not (UnixFileStatus.Regular or UnixFileStatus.Directory or UnixFileStatus.SymbolicLink); /// /// Checks if the given file type is known, equivalent to mode.GetFileType() != . /// /// if the given file type is a known file type, otherwise . + [MethodImpl((MethodImplOptions)0x100)] public bool IsTypeKnown() => mode.GetFileType() != UnixFileStatus.None; /// @@ -208,7 +221,7 @@ public static UnixFileStatus FromPermissionCode(string code) public string ToPermissionCode() { #if HAS_BUFFERS - Span code = stackalloc char[10]; + scoped Span code = stackalloc char[10]; #else char[] code = new char[10]; #endif diff --git a/AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs b/AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs index 4b93efd..af069a1 100644 --- a/AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs +++ b/AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs @@ -3,6 +3,7 @@ // using System; +using System.Diagnostics.CodeAnalysis; namespace AdvancedSharpAdbClient.Logs { @@ -19,7 +20,7 @@ public interface ILogger /// The exception to log. /// Format string of the log message. /// An object array that contains zero or more objects to format. - void Log(LogLevel logLevel, Exception? exception, string? message, params object?[] args); + void Log(LogLevel logLevel, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args); } /// diff --git a/AdvancedSharpAdbClient/Logs/NullLogger.cs b/AdvancedSharpAdbClient/Logs/NullLogger.cs index 104581f..93a2ba9 100644 --- a/AdvancedSharpAdbClient/Logs/NullLogger.cs +++ b/AdvancedSharpAdbClient/Logs/NullLogger.cs @@ -3,6 +3,7 @@ // using System; +using System.Diagnostics.CodeAnalysis; namespace AdvancedSharpAdbClient.Logs { @@ -17,7 +18,7 @@ public class NullLogger : ILogger public static NullLogger Instance { get; } = new(); /// - public void Log(LogLevel logLevel, Exception? exception, string? message, params object?[] args) { } + public void Log(LogLevel logLevel, Exception? exception, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, params object?[] args) { } } /// diff --git a/AdvancedSharpAdbClient/Models/AdbCommandLineStatus.cs b/AdvancedSharpAdbClient/Models/AdbCommandLineStatus.cs index 3e38859..1a90ccc 100644 --- a/AdvancedSharpAdbClient/Models/AdbCommandLineStatus.cs +++ b/AdvancedSharpAdbClient/Models/AdbCommandLineStatus.cs @@ -95,12 +95,12 @@ public static AdbCommandLineStatus GetVersionFromOutput(params IEnumerable /// The output of the adb.exe version command. /// A object that represents the version and path of the adb command line client. - public static AdbCommandLineStatus GetVersionFromOutput(params ReadOnlySpan output) + public static AdbCommandLineStatus GetVersionFromOutput(params scoped ReadOnlySpan output) { int index = 0; Version? adbVersion = null; string? fileVersion = null, filePath = null; - ReadOnlySpan.Enumerator enumerator = output.GetEnumerator(); + scoped ReadOnlySpan.Enumerator enumerator = output.GetEnumerator(); while (index < 3 && enumerator.MoveNext()) { string line = enumerator.Current; diff --git a/AdvancedSharpAdbClient/Models/ColorData.cs b/AdvancedSharpAdbClient/Models/ColorData.cs index 22eef9b..e504e6a 100644 --- a/AdvancedSharpAdbClient/Models/ColorData.cs +++ b/AdvancedSharpAdbClient/Models/ColorData.cs @@ -106,7 +106,7 @@ public readonly IEnumerator GetEnumerator() /// equal to the size of the structure in bytes. public byte[] ToArray() { - ref readonly ColorData data = ref this; + scoped ref readonly ColorData data = ref this; unsafe { byte[] array = new byte[Size]; diff --git a/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs b/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs index 5dee9de..a410385 100644 --- a/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs +++ b/AdvancedSharpAdbClient/Models/DeviceData.EventArgs.cs @@ -26,7 +26,7 @@ public abstract class DeviceDataEventArgs(DeviceData device) : EventArgs /// public override string ToString() { - DefaultInterpolatedStringHandler builder = new(18, 2); + scoped DefaultInterpolatedStringHandler builder = new(18, 2); builder.AppendLiteral("Device changed"); if (!Device.IsEmpty) { @@ -76,7 +76,7 @@ public sealed class DeviceDataConnectEventArgs(DeviceData device, bool isConnect /// public override string ToString() { - DefaultInterpolatedStringHandler builder = new(23, 2); + scoped DefaultInterpolatedStringHandler builder = new(23, 2); builder.AppendLiteral("Device "); builder.AppendLiteral(IsConnect ? "connected" : "disconnected"); if (Device.IsEmpty) @@ -120,7 +120,7 @@ public sealed class DeviceDataChangeEventArgs(DeviceData device, DeviceState new /// public override string ToString() { - DefaultInterpolatedStringHandler builder = new(29, 4); + scoped DefaultInterpolatedStringHandler builder = new(29, 4); builder.AppendLiteral("Device state changed:"); if (!Device.IsEmpty) { diff --git a/AdvancedSharpAdbClient/Models/DeviceData.cs b/AdvancedSharpAdbClient/Models/DeviceData.cs index 9fc3dfa..eb7cbe0 100644 --- a/AdvancedSharpAdbClient/Models/DeviceData.cs +++ b/AdvancedSharpAdbClient/Models/DeviceData.cs @@ -213,7 +213,7 @@ public override string ToString() return $"An empty {GetType()} without {nameof(TransportId)} and {nameof(Serial)}"; } - DefaultInterpolatedStringHandler builder = new(55, 9); + scoped DefaultInterpolatedStringHandler builder = new(55, 9); builder.AppendLiteral(Serial); builder.AppendFormatted('\t'); @@ -337,7 +337,7 @@ public static DeviceState GetStateFromString(string state) /// The value of the for this instance. private string GetDebuggerDisplay() { - DefaultInterpolatedStringHandler builder = new(113, 9); + scoped DefaultInterpolatedStringHandler builder = new(113, 9); builder.AppendFormatted(GetType()); builder.AppendLiteral($" {{ "); diff --git a/AdvancedSharpAdbClient/Models/FileStatistics.Base.cs b/AdvancedSharpAdbClient/Models/FileStatistics.Base.cs index 49d17ca..01992f8 100644 --- a/AdvancedSharpAdbClient/Models/FileStatistics.Base.cs +++ b/AdvancedSharpAdbClient/Models/FileStatistics.Base.cs @@ -14,7 +14,7 @@ namespace AdvancedSharpAdbClient.Models /// The type of the data for file. /// The type of the derived class. /// The for the data of file. - public abstract class FileStatisticsBase(in T data) : IEquatable, IEquatable> + public abstract class FileStatisticsBase(scoped in T data) : IEquatable, IEquatable> #if NET7_0_OR_GREATER , IEqualityOperators, IEqualityOperators, bool> #endif diff --git a/AdvancedSharpAdbClient/Models/FileStatistics.V2.cs b/AdvancedSharpAdbClient/Models/FileStatistics.V2.cs index 7f603f6..883c673 100644 --- a/AdvancedSharpAdbClient/Models/FileStatistics.V2.cs +++ b/AdvancedSharpAdbClient/Models/FileStatistics.V2.cs @@ -13,7 +13,7 @@ namespace AdvancedSharpAdbClient.Models /// /// [DebuggerDisplay($"{{{nameof(GetType)}().{nameof(Type.ToString)}(),nq}} \\{{ {nameof(Path)} = {{{nameof(Path)}}}, {nameof(FileMode)} = {{{nameof(FileMode)}}}, {nameof(Size)} = {{{nameof(Size)}}}, {nameof(ModifiedTime)} = {{{nameof(ModifiedTime)}}} }}")] - public class FileStatisticsEx(in FileStatisticsDataEx data) : FileStatisticsBase(data), IFileStatistics + public class FileStatisticsEx(scoped in FileStatisticsDataEx data) : FileStatisticsBase(data), IFileStatistics #if NET7_0_OR_GREATER , IEqualityOperators #endif diff --git a/AdvancedSharpAdbClient/Models/FileStatistics.cs b/AdvancedSharpAdbClient/Models/FileStatistics.cs index d213a62..1e2f480 100644 --- a/AdvancedSharpAdbClient/Models/FileStatistics.cs +++ b/AdvancedSharpAdbClient/Models/FileStatistics.cs @@ -13,7 +13,7 @@ namespace AdvancedSharpAdbClient.Models /// /// The data of the file. [DebuggerDisplay($"{{{nameof(GetType)}().{nameof(Type.ToString)}(),nq}} \\{{ {nameof(Path)} = {{{nameof(Path)}}}, {nameof(FileMode)} = {{{nameof(FileMode)}}}, {nameof(Size)} = {{{nameof(Size)}}}, {nameof(Time)} = {{{nameof(Time)}}} }}")] - public sealed class FileStatistics(in FileStatisticsData data) : FileStatisticsBase(data), IFileStatistics + public sealed class FileStatistics(scoped in FileStatisticsData data) : FileStatisticsBase(data), IFileStatistics #if NET7_0_OR_GREATER , IEqualityOperators #endif diff --git a/AdvancedSharpAdbClient/Models/FileStatisticsData.V2.cs b/AdvancedSharpAdbClient/Models/FileStatisticsData.V2.cs index f74f57d..8a57903 100644 --- a/AdvancedSharpAdbClient/Models/FileStatisticsData.V2.cs +++ b/AdvancedSharpAdbClient/Models/FileStatisticsData.V2.cs @@ -125,7 +125,7 @@ public unsafe byte[] ToArray() /// Returns a read-only span of bytes representing the contents of this instance. /// /// A that provides a read-only view of the bytes in this instance. - public unsafe ReadOnlySpan AsSpan() => MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref Unsafe.AsRef(in this)), Length); + public ReadOnlySpan AsSpan() => MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref Unsafe.AsRef(in this)), Length); /// /// Returns an enumerator that iterates through the . diff --git a/AdvancedSharpAdbClient/Models/FramebufferHeader.Drawing.cs b/AdvancedSharpAdbClient/Models/FramebufferHeader.Drawing.cs new file mode 100644 index 0000000..41cb022 --- /dev/null +++ b/AdvancedSharpAdbClient/Models/FramebufferHeader.Drawing.cs @@ -0,0 +1,164 @@ +#if HAS_IMAGING +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +using System; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace AdvancedSharpAdbClient.Models +{ + /// + /// Provides extension methods for that allow to convert the raw data contained in a framebuffer to a . + /// + public static class FramebufferHeaderDrawing + { + /// + /// Converts a array containing the raw frame buffer data to a . + /// + /// The header of the frame buffer, which contains information about how the image data is stored in the . + /// The buffer containing the image data. + /// A that represents the image contained in the frame buffer, or + /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. +#if NET + [SupportedOSPlatform("windows6.1")] +#endif + public static Bitmap? ToImage(this scoped in FramebufferHeader header, byte[] buffer) + { + ArgumentNullException.ThrowIfNull(buffer); + + // This happens, for example, when DRM is enabled. In that scenario, no screenshot is taken on the device and an empty + // framebuffer is returned; we'll just return null. + if (header.Width == 0 || header.Height == 0 || header.Bpp == 0) + { + return null; + } + + // The pixel format of the framebuffer may not be one that .NET recognizes, so we need to fix that + PixelFormat pixelFormat = header.StandardizePixelFormat(ref buffer); + + Bitmap bitmap = new((int)header.Width, (int)header.Height, pixelFormat); + BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, pixelFormat); + Marshal.Copy(buffer, 0, bitmapData.Scan0, (int)header.Size); + bitmap.UnlockBits(bitmapData); + + return bitmap; + } + + /// + /// Returns the that describes pixel format of an image that is stored according to the information + /// present in this . Because the enumeration does not allow for all + /// formats supported by Android, this method also takes a and reorganizes the bytes in the buffer to + /// match the return value of this function. + /// + /// The header of the frame buffer, which contains information about how the image data is stored in the . + /// A byte array in which the images are stored according to this . + /// A that describes how the image data is represented in this . +#if NET + [SupportedOSPlatform("windows6.1")] +#endif + private static PixelFormat StandardizePixelFormat(this scoped in FramebufferHeader header, ref byte[] buffer) + { + // Initial parameter validation. + ArgumentNullException.ThrowIfNull(buffer); + + if (buffer.Length < header.Width * header.Height * (header.Bpp / 8)) + { + throw new ArgumentOutOfRangeException(nameof(buffer), $"The buffer length {buffer.Length} is less than expected buffer " + + $"length ({header.Width * header.Height * (header.Bpp / 8)}) for a picture of width {header.Width}, height {header.Height} and pixel depth {header.Bpp}"); + } + + if (header.Width == 0 || header.Height == 0 || header.Bpp == 0) + { + throw new InvalidOperationException("Cannot cannulate the pixel format of an empty framebuffer"); + } + + // By far, the most common format is a 32-bit pixel format, which is either + // RGB or RGBA, where each color has 1 byte. + if (header.Bpp == 8 * 4) + { + // Require at least RGB to be present; and require them to be exactly one byte (8 bits) long. + if (header.Red.Length != 8 || header.Blue.Length != 8 || header.Green.Length != 8) + { + throw new ArgumentOutOfRangeException($"The pixel format with with RGB lengths of {header.Red.Length}:{header.Blue.Length}:{header.Green.Length} is not supported"); + } + + // Alpha can be present or absent, but must be 8 bytes long + if (header.Alpha.Length is not (0 or 8)) + { + throw new ArgumentOutOfRangeException($"The alpha length {header.Alpha.Length} is not supported"); + } + + // Gets the index at which the red, bue, green and alpha values are stored. + int redIndex = (int)header.Red.Offset / 8; + int blueIndex = (int)header.Blue.Offset / 8; + int greenIndex = (int)header.Green.Offset / 8; + int alphaIndex = (int)header.Alpha.Offset / 8; + + byte[] array = new byte[(int)header.Size * 4]; + // Loop over the array and re-order as required + for (int i = 0; i < (int)header.Size; i += 4) + { + byte red = buffer[i + redIndex]; + byte blue = buffer[i + blueIndex]; + byte green = buffer[i + greenIndex]; + byte alpha = buffer[i + alphaIndex]; + + // Convert to ARGB. Note, we're on a little endian system, + // so it's really BGRA. Confusing! + if (header.Alpha.Length == 8) + { + array[i + 3] = alpha; + array[i + 2] = red; + array[i + 1] = green; + array[i + 0] = blue; + } + else + { + array[i + 3] = 0; + array[i + 2] = red; + array[i + 1] = green; + array[i + 0] = blue; + } + } + buffer = array; + + // Returns RGB or RGBA, function of the presence of an alpha channel. + return header.Alpha.Length == 0 ? PixelFormat.Format32bppRgb : PixelFormat.Format32bppArgb; + } + else if (header.Bpp == 8 * 3) + { + // For 24-bit image depths, we only support RGB. + if (header.Red.Offset == 0 + && header.Red.Length == 8 + && header.Green.Offset == 8 + && header.Green.Length == 8 + && header.Blue.Offset == 16 + && header.Blue.Length == 8 + && header.Alpha.Offset == 24 + && header.Alpha.Length == 0) + { + return PixelFormat.Format24bppRgb; + } + } + else if (header.Bpp == 5 + 6 + 5 + && header.Red.Offset == 11 + && header.Red.Length == 5 + && header.Green.Offset == 5 + && header.Green.Length == 6 + && header.Blue.Offset == 0 + && header.Blue.Length == 5 + && header.Alpha.Offset == 0 + && header.Alpha.Length == 0) + { + // For 16-bit image depths, we only support Rgb565. + return PixelFormat.Format16bppRgb565; + } + + // If not caught by any of the statements before, the format is not supported. + throw new NotSupportedException($"Pixel depths of {header.Bpp} are not supported"); + } + } +} +#endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Models/FramebufferHeader.WinRT.cs b/AdvancedSharpAdbClient/Models/FramebufferHeader.WinRT.cs new file mode 100644 index 0000000..67ecd38 --- /dev/null +++ b/AdvancedSharpAdbClient/Models/FramebufferHeader.WinRT.cs @@ -0,0 +1,185 @@ +#if HAS_WUXC +// +// Copyright (c) The Android Open Source Project, Ryan Conrad, Quamotion, yungd1plomat, wherewhere. All rights reserved. +// + +using System; +using System.Threading; + +namespace AdvancedSharpAdbClient.Models +{ + /// + /// Provides extension methods for that allow to convert the raw data contained in a framebuffer to a . + /// + public static class FramebufferHeaderWinRT + { + /// + /// Gets is supported. + /// +#if NET + [SupportedOSPlatformGuard("Windows10.0.18362.0")] +#endif + public static bool IsHasThreadAccessSupported { get; } = ApiInformation.IsMethodPresent("Windows.System.DispatcherQueue", "HasThreadAccess"); + + /// + /// Converts a array containing the raw frame buffer data to a . + /// + /// The header of the frame buffer, which contains information about how the image data is stored in the . + /// The buffer containing the image data. + /// The target to invoke the code on. + /// A which can be used to cancel the asynchronous task. + /// A that represents the image contained in the frame buffer, or + /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. + public static Task ToBitmapAsync(this scoped in FramebufferHeader header, byte[] buffer, CoreDispatcher dispatcher, CancellationToken cancellationToken = default) + { + if (dispatcher.HasThreadAccess) + { + return header.ToBitmapAsync(buffer, cancellationToken); + } + else + { + FramebufferHeader self = header; + TaskCompletionSource taskCompletionSource = new(); + _ = dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => + { + try + { + WriteableBitmap? result = await self.ToBitmapAsync(buffer, cancellationToken).ConfigureAwait(false); + _ = taskCompletionSource.TrySetResult(result); + } + catch (Exception e) + { + _ = taskCompletionSource.TrySetException(e); + } + }); + return taskCompletionSource.Task; + } + } + + /// + /// Converts a array containing the raw frame buffer data to a . + /// + /// The header of the frame buffer, which contains information about how the image data is stored in the . + /// The buffer containing the image data. + /// The target to invoke the code on. + /// A which can be used to cancel the asynchronous task. + /// A that represents the image contained in the frame buffer, or + /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. +#if NET + [SupportedOSPlatform("Windows10.0.16299.0")] +#endif + [ContractVersion(typeof(UniversalApiContract), 0x50000u)] + public static Task ToBitmapAsync(this scoped in FramebufferHeader header, byte[] buffer, DispatcherQueue dispatcher, CancellationToken cancellationToken = default) + { + if (IsHasThreadAccessSupported && dispatcher.HasThreadAccess) + { + return header.ToBitmapAsync(buffer, cancellationToken); + } + else + { + FramebufferHeader self = header; + TaskCompletionSource taskCompletionSource = new(); + if (!dispatcher.TryEnqueue(async () => + { + try + { + WriteableBitmap? result = await self.ToBitmapAsync(buffer, cancellationToken).ConfigureAwait(false); + _ = taskCompletionSource.TrySetResult(result); + } + catch (Exception e) + { + _ = taskCompletionSource.TrySetException(e); + } + })) + { + _ = taskCompletionSource.TrySetException(new InvalidOperationException("Failed to enqueue the operation")); + } + return taskCompletionSource.Task; + } + } + + /// + /// Converts a array containing the raw frame buffer data to a . + /// + /// The header of the frame buffer, which contains information about how the image data is stored in the . + /// The buffer containing the image data. + /// A which can be used to cancel the asynchronous task. + /// A that represents the image contained in the frame buffer, or + /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. + public static async Task ToBitmapAsync(this FramebufferHeader header, byte[] buffer, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(buffer); + + // This happens, for example, when DRM is enabled. In that scenario, no screenshot is taken on the device and an empty + // framebuffer is returned; we'll just return null. + if (header.Width == 0 || header.Height == 0 || header.Bpp == 0) + { + return null; + } + + // The pixel format of the framebuffer may not be one that WinRT recognizes, so we need to fix that + BitmapPixelFormat bitmapPixelFormat = header.StandardizePixelFormat(buffer, out BitmapAlphaMode alphaMode); + + using InMemoryRandomAccessStream random = new(); + BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, random).AsTask(cancellationToken); + encoder.SetPixelData(bitmapPixelFormat, alphaMode, header.Width, header.Height, 96, 96, buffer); + await encoder.FlushAsync().AsTask(cancellationToken); + WriteableBitmap WriteableImage = new((int)header.Width, (int)header.Height); + await WriteableImage.SetSourceAsync(random).AsTask(cancellationToken).ConfigureAwait(false); + + return WriteableImage; + } + + /// + /// Returns the that describes pixel format of an image that is stored according to the information + /// present in this . Because the enumeration does not allow for all + /// formats supported by Android, this method also takes a and reorganizes the bytes in the buffer to + /// match the return value of this function. + /// + /// The header of the frame buffer, which contains information about how the image data is stored in the . + /// A byte array in which the images are stored according to this . + /// A which describes how the alpha channel is stored. + /// A that describes how the image data is represented in this . + private static BitmapPixelFormat StandardizePixelFormat(this scoped in FramebufferHeader header, byte[] buffer, out BitmapAlphaMode alphaMode) + { + // Initial parameter validation. + ArgumentNullException.ThrowIfNull(buffer); + + if (buffer.Length < header.Width * header.Height * (header.Bpp / 8)) + { + throw new ArgumentOutOfRangeException(nameof(buffer), $"The buffer length {buffer.Length} is less than expected buffer " + + $"length ({header.Width * header.Height * (header.Bpp / 8)}) for a picture of width {header.Width}, height {header.Height} and pixel depth {header.Bpp}"); + } + + if (header.Width == 0 || header.Height == 0 || header.Bpp == 0) + { + throw new InvalidOperationException("Cannot cannulate the pixel format of an empty framebuffer"); + } + + // By far, the most common format is a 32-bit pixel format, which is either + // RGB or RGBA, where each color has 1 byte. + if (header.Bpp == 8 * 4) + { + // Require at least RGB to be present; and require them to be exactly one byte (8 bits) long. + if (header.Red.Length != 8 || header.Blue.Length != 8 || header.Green.Length != 8) + { + throw new ArgumentOutOfRangeException($"The pixel format with with RGB lengths of {header.Red.Length}:{header.Blue.Length}:{header.Green.Length} is not supported"); + } + + // Alpha can be present or absent, but must be 8 bytes long + alphaMode = header.Alpha.Length switch + { + 0 => BitmapAlphaMode.Ignore, + 8 => BitmapAlphaMode.Straight, + _ => throw new ArgumentOutOfRangeException($"The alpha length {header.Alpha.Length} is not supported"), + }; + + return BitmapPixelFormat.Rgba8; + } + + // If not caught by any of the statements before, the format is not supported. + throw new NotSupportedException($"Pixel depths of {header.Bpp} are not supported"); + } + } +} +#endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Models/FramebufferHeader.cs b/AdvancedSharpAdbClient/Models/FramebufferHeader.cs index abf663e..b2afdf3 100644 --- a/AdvancedSharpAdbClient/Models/FramebufferHeader.cs +++ b/AdvancedSharpAdbClient/Models/FramebufferHeader.cs @@ -6,14 +6,9 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Drawing; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -#if HAS_WUXC -using System.Threading; -#endif - namespace AdvancedSharpAdbClient.Models { /// @@ -44,7 +39,7 @@ namespace AdvancedSharpAdbClient.Models /// The data that feeds the struct. public FramebufferHeader(byte[] data) { - byte[] _data; + byte[] source; switch (data) { // Technically, 0 is not a supported version either; we assume version 0 indicates @@ -56,16 +51,15 @@ public FramebufferHeader(byte[] data) case [2, ..]: goto default; case [< 2, ..]: - _data = new byte[MaxLength]; - Array.Copy(data, 0, _data, 0, 2 * sizeof(uint)); - Array.Copy(data, 2 * sizeof(uint), _data, (2 * sizeof(uint)) + 4, MinLength - (2 * sizeof(uint))); + source = new byte[MaxLength]; + Array.Copy(data, 0, source, 0, 2 * sizeof(uint)); + Array.Copy(data, 2 * sizeof(uint), source, (2 * sizeof(uint)) + 4, MinLength - (2 * sizeof(uint))); break; default: - _data = data; + source = data; break; } - - this = Unsafe.As(ref _data[0]); + this = Unsafe.As(ref source[0]); } #if HAS_BUFFERS @@ -74,9 +68,9 @@ public FramebufferHeader(byte[] data) /// /// The data that feeds the struct. [OverloadResolutionPriority(1)] - public FramebufferHeader(ReadOnlySpan data) + public FramebufferHeader(scoped in ReadOnlySpan data) { - ReadOnlySpan _data = data switch + scoped ReadOnlySpan source = data switch { { Length: < MinLength or > MaxLength } => throw new ArgumentOutOfRangeException(nameof(data), $"The length of {nameof(data)} must be {MinLength} or {MaxLength}."), // Technically, 0 is not a supported version either; we assume version 0 indicates @@ -85,8 +79,7 @@ public FramebufferHeader(ReadOnlySpan data) [2, ..] => data, [< 2, ..] => [.. data[..(2 * sizeof(uint))], 0, 0, 0, 0, .. data[(2 * sizeof(uint))..]] }; - - this = Unsafe.As(ref MemoryMarshal.GetReference(_data)); + this = Unsafe.As(ref MemoryMarshal.GetReference(source)); } #endif @@ -204,325 +197,13 @@ public byte this[int index] /// The data that feeds the struct. /// A new object. [OverloadResolutionPriority(1)] - public static FramebufferHeader Read(ReadOnlySpan data) => new(data); -#endif - -#if HAS_IMAGING - /// - /// Converts a array containing the raw frame buffer data to a . - /// - /// The buffer containing the image data. - /// A that represents the image contained in the frame buffer, or - /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. -#if NET - [SupportedOSPlatform("windows6.1")] -#endif - public Bitmap? ToImage(byte[] buffer) - { - ArgumentNullException.ThrowIfNull(buffer); - - // This happens, for example, when DRM is enabled. In that scenario, no screenshot is taken on the device and an empty - // framebuffer is returned; we'll just return null. - if (Width == 0 || Height == 0 || Bpp == 0) - { - return null; - } - - // The pixel format of the framebuffer may not be one that .NET recognizes, so we need to fix that - PixelFormat pixelFormat = StandardizePixelFormat(ref buffer); - - Bitmap bitmap = new((int)Width, (int)Height, pixelFormat); - BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, pixelFormat); - Marshal.Copy(buffer, 0, bitmapData.Scan0, (int)Size); - bitmap.UnlockBits(bitmapData); - - return bitmap; - } - - /// - /// Returns the that describes pixel format of an image that is stored according to the information - /// present in this . Because the enumeration does not allow for all - /// formats supported by Android, this method also takes a and reorganizes the bytes in the buffer to - /// match the return value of this function. - /// - /// A byte array in which the images are stored according to this . - /// A that describes how the image data is represented in this . -#if NET - [SupportedOSPlatform("windows6.1")] -#endif - private PixelFormat StandardizePixelFormat(ref byte[] buffer) - { - // Initial parameter validation. - ArgumentNullException.ThrowIfNull(buffer); - - if (buffer.Length < Width * Height * (Bpp / 8)) - { - throw new ArgumentOutOfRangeException(nameof(buffer), $"The buffer length {buffer.Length} is less than expected buffer " + - $"length ({Width * Height * (Bpp / 8)}) for a picture of width {Width}, height {Height} and pixel depth {Bpp}"); - } - - if (Width == 0 || Height == 0 || Bpp == 0) - { - throw new InvalidOperationException("Cannot cannulate the pixel format of an empty framebuffer"); - } - - // By far, the most common format is a 32-bit pixel format, which is either - // RGB or RGBA, where each color has 1 byte. - if (Bpp == 8 * 4) - { - // Require at least RGB to be present; and require them to be exactly one byte (8 bits) long. - if (Red.Length != 8 || Blue.Length != 8 || Green.Length != 8) - { - throw new ArgumentOutOfRangeException($"The pixel format with with RGB lengths of {Red.Length}:{Blue.Length}:{Green.Length} is not supported"); - } - - // Alpha can be present or absent, but must be 8 bytes long - if (Alpha.Length is not (0 or 8)) - { - throw new ArgumentOutOfRangeException($"The alpha length {Alpha.Length} is not supported"); - } - - // Gets the index at which the red, bue, green and alpha values are stored. - int redIndex = (int)Red.Offset / 8; - int blueIndex = (int)Blue.Offset / 8; - int greenIndex = (int)Green.Offset / 8; - int alphaIndex = (int)Alpha.Offset / 8; - - byte[] array = new byte[(int)Size * 4]; - // Loop over the array and re-order as required - for (int i = 0; i < (int)Size; i += 4) - { - byte red = buffer[i + redIndex]; - byte blue = buffer[i + blueIndex]; - byte green = buffer[i + greenIndex]; - byte alpha = buffer[i + alphaIndex]; - - // Convert to ARGB. Note, we're on a little endian system, - // so it's really BGRA. Confusing! - if (Alpha.Length == 8) - { - array[i + 3] = alpha; - array[i + 2] = red; - array[i + 1] = green; - array[i + 0] = blue; - } - else - { - array[i + 3] = 0; - array[i + 2] = red; - array[i + 1] = green; - array[i + 0] = blue; - } - } - buffer = array; - - // Returns RGB or RGBA, function of the presence of an alpha channel. - return Alpha.Length == 0 ? PixelFormat.Format32bppRgb : PixelFormat.Format32bppArgb; - } - else if (Bpp == 8 * 3) - { - // For 24-bit image depths, we only support RGB. - if (Red.Offset == 0 - && Red.Length == 8 - && Green.Offset == 8 - && Green.Length == 8 - && Blue.Offset == 16 - && Blue.Length == 8 - && Alpha.Offset == 24 - && Alpha.Length == 0) - { - return PixelFormat.Format24bppRgb; - } - } - else if (Bpp == 5 + 6 + 5 - && Red.Offset == 11 - && Red.Length == 5 - && Green.Offset == 5 - && Green.Length == 6 - && Blue.Offset == 0 - && Blue.Length == 5 - && Alpha.Offset == 0 - && Alpha.Length == 0) - { - // For 16-bit image depths, we only support Rgb565. - return PixelFormat.Format16bppRgb565; - } - - // If not caught by any of the statements before, the format is not supported. - throw new NotSupportedException($"Pixel depths of {Bpp} are not supported"); - } -#endif - -#if HAS_WUXC - /// - /// Gets is supported. - /// -#if NET - [SupportedOSPlatformGuard("Windows10.0.18362.0")] -#endif - public static bool IsHasThreadAccessSupported { get; } = ApiInformation.IsMethodPresent("Windows.System.DispatcherQueue", "HasThreadAccess"); - - /// - /// Converts a array containing the raw frame buffer data to a . - /// - /// The buffer containing the image data. - /// The target to invoke the code on. - /// A which can be used to cancel the asynchronous task. - /// A that represents the image contained in the frame buffer, or - /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. - public Task ToBitmapAsync(byte[] buffer, CoreDispatcher dispatcher, CancellationToken cancellationToken = default) - { - if (dispatcher.HasThreadAccess) - { - return ToBitmapAsync(buffer, cancellationToken); - } - else - { - FramebufferHeader self = this; - TaskCompletionSource taskCompletionSource = new(); - _ = dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => - { - try - { - WriteableBitmap? result = await self.ToBitmapAsync(buffer, cancellationToken).ConfigureAwait(false); - _ = taskCompletionSource.TrySetResult(result); - } - catch (Exception e) - { - _ = taskCompletionSource.TrySetException(e); - } - }); - return taskCompletionSource.Task; - } - } - - /// - /// Converts a array containing the raw frame buffer data to a . - /// - /// The buffer containing the image data. - /// The target to invoke the code on. - /// A which can be used to cancel the asynchronous task. - /// A that represents the image contained in the frame buffer, or - /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. -#if NET - [SupportedOSPlatform("Windows10.0.16299.0")] -#endif - [ContractVersion(typeof(UniversalApiContract), 0x50000u)] - public Task ToBitmapAsync(byte[] buffer, DispatcherQueue dispatcher, CancellationToken cancellationToken = default) - { - if (IsHasThreadAccessSupported && dispatcher.HasThreadAccess) - { - return ToBitmapAsync(buffer, cancellationToken); - } - else - { - FramebufferHeader self = this; - TaskCompletionSource taskCompletionSource = new(); - if (!dispatcher.TryEnqueue(async () => - { - try - { - WriteableBitmap? result = await self.ToBitmapAsync(buffer, cancellationToken).ConfigureAwait(false); - _ = taskCompletionSource.TrySetResult(result); - } - catch (Exception e) - { - _ = taskCompletionSource.TrySetException(e); - } - })) - { - _ = taskCompletionSource.TrySetException(new InvalidOperationException("Failed to enqueue the operation")); - } - return taskCompletionSource.Task; - } - } - - /// - /// Converts a array containing the raw frame buffer data to a . - /// - /// The buffer containing the image data. - /// A which can be used to cancel the asynchronous task. - /// A that represents the image contained in the frame buffer, or - /// if the framebuffer does not contain any data. This can happen when DRM is enabled on the device. - public async Task ToBitmapAsync(byte[] buffer, CancellationToken cancellationToken = default) - { - ArgumentNullException.ThrowIfNull(buffer); - - // This happens, for example, when DRM is enabled. In that scenario, no screenshot is taken on the device and an empty - // framebuffer is returned; we'll just return null. - if (Width == 0 || Height == 0 || Bpp == 0) - { - return null; - } - - // The pixel format of the framebuffer may not be one that WinRT recognizes, so we need to fix that - BitmapPixelFormat bitmapPixelFormat = StandardizePixelFormat(buffer, out BitmapAlphaMode alphaMode); - - using InMemoryRandomAccessStream random = new(); - BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, random).AsTask(cancellationToken); - encoder.SetPixelData(bitmapPixelFormat, alphaMode, Width, Height, 96, 96, buffer); - await encoder.FlushAsync().AsTask(cancellationToken); - WriteableBitmap WriteableImage = new((int)Width, (int)Height); - await WriteableImage.SetSourceAsync(random).AsTask(cancellationToken).ConfigureAwait(false); - - return WriteableImage; - } - - /// - /// Returns the that describes pixel format of an image that is stored according to the information - /// present in this . Because the enumeration does not allow for all - /// formats supported by Android, this method also takes a and reorganizes the bytes in the buffer to - /// match the return value of this function. - /// - /// A byte array in which the images are stored according to this . - /// A which describes how the alpha channel is stored. - /// A that describes how the image data is represented in this . - private BitmapPixelFormat StandardizePixelFormat(byte[] buffer, out BitmapAlphaMode alphaMode) - { - // Initial parameter validation. - ArgumentNullException.ThrowIfNull(buffer); - - if (buffer.Length < Width * Height * (Bpp / 8)) - { - throw new ArgumentOutOfRangeException(nameof(buffer), $"The buffer length {buffer.Length} is less than expected buffer " + - $"length ({Width * Height * (Bpp / 8)}) for a picture of width {Width}, height {Height} and pixel depth {Bpp}"); - } - - if (Width == 0 || Height == 0 || Bpp == 0) - { - throw new InvalidOperationException("Cannot cannulate the pixel format of an empty framebuffer"); - } - - // By far, the most common format is a 32-bit pixel format, which is either - // RGB or RGBA, where each color has 1 byte. - if (Bpp == 8 * 4) - { - // Require at least RGB to be present; and require them to be exactly one byte (8 bits) long. - if (Red.Length != 8 || Blue.Length != 8 || Green.Length != 8) - { - throw new ArgumentOutOfRangeException($"The pixel format with with RGB lengths of {Red.Length}:{Blue.Length}:{Green.Length} is not supported"); - } - - // Alpha can be present or absent, but must be 8 bytes long - alphaMode = Alpha.Length switch - { - 0 => BitmapAlphaMode.Ignore, - 8 => BitmapAlphaMode.Straight, - _ => throw new ArgumentOutOfRangeException($"The alpha length {Alpha.Length} is not supported"), - }; - - return BitmapPixelFormat.Rgba8; - } - - // If not caught by any of the statements before, the format is not supported. - throw new NotSupportedException($"Pixel depths of {Bpp} are not supported"); - } + public static FramebufferHeader Read(scoped ReadOnlySpan data) => new(data); #endif /// public override string ToString() { - DefaultInterpolatedStringHandler handler = new(121, 10); + scoped DefaultInterpolatedStringHandler handler = new(121, 10); handler.AppendFormatted(GetType()); handler.AppendLiteral($" {{ {nameof(Version)} = "); handler.AppendFormatted(Version); diff --git a/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs b/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs index 088cbed..b3f5b8e 100644 --- a/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs +++ b/AdvancedSharpAdbClient/Models/InstallProgress.EventArgs.cs @@ -88,7 +88,7 @@ public override string ToString() split.Add(c); } - DefaultInterpolatedStringHandler builder = new(4, 4); + scoped DefaultInterpolatedStringHandler builder = new(4, 4); #if NET builder.AppendFormatted(CollectionsMarshal.AsSpan(split)); #elif HAS_BUFFERS diff --git a/AdvancedSharpAdbClient/Models/ShellStream.cs b/AdvancedSharpAdbClient/Models/ShellStream.cs index 09c6c93..b13bc35 100644 --- a/AdvancedSharpAdbClient/Models/ShellStream.cs +++ b/AdvancedSharpAdbClient/Models/ShellStream.cs @@ -70,7 +70,7 @@ public override long Position #if HAS_BUFFERS /// - public override int Read(Span buffer) + public override int Read(scoped Span buffer) { if (buffer.Length == 0) { diff --git a/AdvancedSharpAdbClient/Polyfills/Attributes/ExcludeFromCodeCoverageAttribute.cs b/AdvancedSharpAdbClient/Polyfills/Attributes/ExcludeFromCodeCoverageAttribute.cs new file mode 100644 index 0000000..c268226 --- /dev/null +++ b/AdvancedSharpAdbClient/Polyfills/Attributes/ExcludeFromCodeCoverageAttribute.cs @@ -0,0 +1,19 @@ +#if !NET40_OR_GREATER && !NETCOREAPP && !COMP_NETSTANDARD2_0 +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that the attributed code should be excluded from code coverage information. + /// + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)] + public sealed class ExcludeFromCodeCoverageAttribute : Attribute + { + /// + /// Gets or sets the justification for excluding the member from code coverage. + /// + public string? Justification { get; set; } + } +} +#endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/BitConverterExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/BitConverterExtensions.cs index 60eafe3..0d846a1 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/BitConverterExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/BitConverterExtensions.cs @@ -4,6 +4,7 @@ // using System; +using System.Runtime.CompilerServices; namespace AdvancedSharpAdbClient.Polyfills { @@ -22,6 +23,7 @@ internal static class BitConverterExtensions /// /// An array of bytes that includes the four bytes to convert. /// A 32-bit signed integer representing the converted bytes. + [MethodImpl((MethodImplOptions)0x100)] public static int ToInt32(byte[] value) => BitConverter.ToInt32(value, 0); /// @@ -29,6 +31,7 @@ internal static class BitConverterExtensions /// /// The array of bytes that includes the two bytes to convert. /// An 16-bit unsigned integer representing the converted bytes. + [MethodImpl((MethodImplOptions)0x100)] public static ushort ToUInt16(byte[] value) => BitConverter.ToUInt16(value, 0); /// @@ -36,6 +39,7 @@ internal static class BitConverterExtensions /// /// An array of bytes. /// A 32-bit unsigned integer representing the converted bytes. + [MethodImpl((MethodImplOptions)0x100)] public static uint ToUInt32(byte[] value) => BitConverter.ToUInt32(value, 0); } } diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs index 7f8391f..736798e 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/ExceptionExtensions.cs @@ -4,6 +4,7 @@ // using System; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/OperatingSystemExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/OperatingSystemExtensions.cs index a82a07a..7107a12 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/OperatingSystemExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/OperatingSystemExtensions.cs @@ -5,6 +5,7 @@ using System; using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace AdvancedSharpAdbClient.Polyfills @@ -23,6 +24,7 @@ internal static class OperatingSystemExtensions /// /// Indicates whether the current application is running on Windows. /// + [MethodImpl((MethodImplOptions)0x100)] public static bool IsWindows() => #if NETCORE && !UAP10_0_15138_0 true; @@ -40,6 +42,7 @@ or PlatformID.WinCE /// /// Indicates whether the current application is running on Linux. /// + [MethodImpl((MethodImplOptions)0x100)] public static bool IsLinux() => #if NETCORE && !UAP10_0_15138_0 false; @@ -52,6 +55,7 @@ public static bool IsLinux() => /// /// Indicates whether the current application is running on macOS. /// + [MethodImpl((MethodImplOptions)0x100)] public static bool IsMacOS() => #if NETCORE && !UAP10_0_15138_0 false; @@ -63,6 +67,7 @@ public static bool IsMacOS() => /// /// Indicates whether the current application is running on FreeBSD. /// + [MethodImpl((MethodImplOptions)0x100)] public static bool IsFreeBSD() => #if NETCOREAPP3_0_OR_GREATER RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD); diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs index 18c53b4..6369c61 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/SocketExtensions.cs @@ -7,6 +7,7 @@ using System.ComponentModel; using System.Net; using System.Net.Sockets; +using System.Runtime.CompilerServices; using System.Threading; namespace AdvancedSharpAdbClient.Polyfills @@ -25,6 +26,7 @@ internal static class SocketExtensions /// The endpoint to connect to. /// A cancellation token that can be used to cancel the asynchronous operation. /// An asynchronous task that completes when the connection is established. + [MethodImpl((MethodImplOptions)0x100)] public static Task ConnectAsync(this Socket socket, EndPoint remoteEP, CancellationToken cancellationToken) => Task.Run(() => socket.Connect(remoteEP), cancellationToken); #endif @@ -39,6 +41,7 @@ public static Task ConnectAsync(this Socket socket, EndPoint remoteEP, Cancellat /// A which can be used to cancel the asynchronous task. /// Cancelling the task will also close the socket. /// A which returns the number of bytes received. + [MethodImpl((MethodImplOptions)0x100)] public static Task ReceiveAsync(this Socket socket, byte[] buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => socket.ReceiveAsync(buffer, 0, buffer.Length, socketFlags, cancellationToken); #endif @@ -53,6 +56,7 @@ public static Task ReceiveAsync(this Socket socket, byte[] buffer, SocketFl /// A which can be used to cancel the asynchronous task. /// Cancelling the task will also close the socket. /// A which returns the number of bytes received. + [MethodImpl((MethodImplOptions)0x100)] public static Task ReceiveAsync(this Socket socket, byte[] buffer, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => socket.ReceiveAsync(buffer, 0, size, socketFlags, cancellationToken); @@ -118,6 +122,7 @@ public static Task ReceiveAsync(this Socket socket, byte[] buffer, int offs /// A which can be used to cancel the asynchronous task. /// Cancelling the task will also close the socket. /// A which returns the number of bytes sent. + [MethodImpl((MethodImplOptions)0x100)] public static Task SendAsync(this Socket socket, byte[] buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) => socket.SendAsync(buffer, 0, buffer.Length, socketFlags, cancellationToken); #endif @@ -132,6 +137,7 @@ public static Task SendAsync(this Socket socket, byte[] buffer, SocketFlags /// A which can be used to cancel the asynchronous task. /// Cancelling the task will also close the socket. /// A which returns the number of bytes sent. + [MethodImpl((MethodImplOptions)0x100)] public static Task SendAsync(this Socket socket, byte[] buffer, int size, SocketFlags socketFlags, CancellationToken cancellationToken = default) => socket.SendAsync(buffer, 0, size, socketFlags, cancellationToken); diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs index 6258670..eff6709 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/StringExtensions.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Text; namespace AdvancedSharpAdbClient.Polyfills @@ -56,6 +57,7 @@ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value) /// One of the enumeration values that specifies the rules to use in the comparison. /// if the parameter occurs within this string, /// or if is the empty string (""); otherwise, . + [MethodImpl((MethodImplOptions)0x100)] public bool Contains(string value, StringComparison comparisonType) => text.IndexOf(value, comparisonType) >= 0; /// @@ -64,6 +66,7 @@ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value) /// A character that delimits the substrings in this string. /// A bitwise combination of the enumeration values that specifies whether to trim substrings and include empty substrings. /// An array whose elements contain the substrings from this instance that are delimited by . + [MethodImpl((MethodImplOptions)0x100)] public string[] Split(char separator, StringSplitOptions options = StringSplitOptions.None) => text.Split([separator], options); /// @@ -76,6 +79,7 @@ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value) /// The maximum number of elements expected in the array. /// A bitwise combination of the enumeration values that specifies whether to trim substrings and include empty substrings. /// An array that contains at most count substrings from this instance that are delimited by . + [MethodImpl((MethodImplOptions)0x100)] public string[] Split(char separator, int count, StringSplitOptions options = StringSplitOptions.None) => text.Split([separator], count, options); /// @@ -83,6 +87,7 @@ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value) /// /// The character to compare. /// if matches the beginning of this string; otherwise, . + [MethodImpl((MethodImplOptions)0x100)] public bool StartsWith(char value) => text.StartsWith(new string([value])); /// @@ -90,6 +95,7 @@ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value) /// /// The character to compare to the character at the end of this instance. /// if matches the end of this instance; otherwise, . + [MethodImpl((MethodImplOptions)0x100)] public bool EndsWith(char value) => text.EndsWith(new string([value])); /// diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/TaskCompletionSourceExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/TaskCompletionSourceExtensions.cs index 4e9a26e..a9eec07 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/TaskCompletionSourceExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/TaskCompletionSourceExtensions.cs @@ -1,5 +1,6 @@ #if !NET && HAS_TASK global using TaskCompletionSource = System.Threading.Tasks.TaskCompletionSource; +using System.Runtime.CompilerServices; namespace AdvancedSharpAdbClient.Polyfills { @@ -13,6 +14,7 @@ internal static class TaskCompletionSourceExtensions /// /// The to set the result for. /// if the operation was successful; otherwise, . + [MethodImpl((MethodImplOptions)0x100)] public static bool TrySetResult(this TaskCompletionSource source) => source.TrySetResult(null); } } diff --git a/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs b/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs index 5187655..1248d4f 100644 --- a/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs +++ b/AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Threading; #if NET40 @@ -54,6 +55,7 @@ internal static class TaskExExtensions /// A Task that represents the work queued to execute in the ThreadPool. /// The parameter was null. /// The associated with was disposed. + [MethodImpl((MethodImplOptions)0x100)] public static Task Run(Action action, CancellationToken cancellationToken) => TaskEx.Run(action, cancellationToken); /// @@ -62,6 +64,7 @@ internal static class TaskExExtensions /// The work to execute asynchronously /// A that represents the work queued to execute in the ThreadPool. /// The parameter was null. + [MethodImpl((MethodImplOptions)0x100)] public static Task Run(Func function) => TaskEx.Run(function); /// @@ -72,6 +75,7 @@ internal static class TaskExExtensions /// A that represents the work queued to execute in the ThreadPool. /// The parameter was null. /// The associated with was disposed. + [MethodImpl((MethodImplOptions)0x100)] public static Task Run(Func function, CancellationToken cancellationToken) => TaskEx.Run(function, cancellationToken); /// @@ -81,6 +85,7 @@ internal static class TaskExExtensions /// A cancellation token to observe while waiting for the task to complete. /// A task that represents the time delay. /// The argument is less than -1. + [MethodImpl((MethodImplOptions)0x100)] public static Task Delay(int dueTime, CancellationToken cancellationToken = default) => TaskEx.Delay(dueTime, cancellationToken); /// @@ -89,6 +94,7 @@ internal static class TaskExExtensions /// The type of the result returned by the task. /// The result to store into the completed task. /// The successfully completed task. + [MethodImpl((MethodImplOptions)0x100)] public static Task FromResult(TResult result) => TaskEx.FromResult(result); #endif } @@ -99,6 +105,7 @@ internal static class TaskExExtensions /// /// The tasks to wait on for completion. /// A task that represents the completion of all of the supplied tasks. + [MethodImpl((MethodImplOptions)0x100)] public static Task WhenAll(this IEnumerable tasks) => #if NETFRAMEWORK && !NET45_OR_GREATER TaskEx @@ -113,6 +120,7 @@ public static Task WhenAll(this IEnumerable tasks) => /// The type of the completed task. /// The tasks to wait on for completion. /// A task that represents the completion of all of the supplied tasks. + [MethodImpl((MethodImplOptions)0x100)] public static Task WhenAll(this IEnumerable> tasks) => #if NETFRAMEWORK && !NET45_OR_GREATER TaskEx diff --git a/AdvancedSharpAdbClient/Polyfills/StringHandler.cs b/AdvancedSharpAdbClient/Polyfills/StringHandler.cs index 2c4d078..d4183e5 100644 --- a/AdvancedSharpAdbClient/Polyfills/StringHandler.cs +++ b/AdvancedSharpAdbClient/Polyfills/StringHandler.cs @@ -278,7 +278,7 @@ public void AppendFormatted(string? value, int alignment = 0, string? format = n /// Writes the specified character span to the handler. /// /// The span to write. - public void AppendFormatted(ReadOnlySpan value) => _ = _stringBuilder.Append(value); + public void AppendFormatted(scoped ReadOnlySpan value) => _ = _stringBuilder.Append(value); /// /// Writes the specified string of chars to the handler. @@ -286,7 +286,7 @@ public void AppendFormatted(string? value, int alignment = 0, string? format = n /// The span to write. /// Minimum number of characters that should be written for this value. If the value is negative, it indicates left-aligned and the required minimum is the absolute value. /// The format string. - public void AppendFormatted(ReadOnlySpan value, int alignment = 0, string? __ = null) + public void AppendFormatted(scoped ReadOnlySpan value, int alignment = 0, string? __ = null) { bool leftAlign = false; if (alignment < 0) @@ -428,5 +428,5 @@ private void AppendOrInsertAlignmentIfNeeded(int startingPos, int alignment) } } #else - [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.DefaultInterpolatedStringHandler))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.DefaultInterpolatedStringHandler))] #endif \ No newline at end of file diff --git a/AdvancedSharpAdbClient/SyncService.Async.cs b/AdvancedSharpAdbClient/SyncService.Async.cs index 853b15a..d59d823 100644 --- a/AdvancedSharpAdbClient/SyncService.Async.cs +++ b/AdvancedSharpAdbClient/SyncService.Async.cs @@ -684,7 +684,7 @@ protected async Task ReadStatisticsAsync(CancellationToken cance #else byte[] statResult = new byte[FileStatisticsData.Length]; _ = await Socket.ReadAsync(statResult, cancellationToken).ConfigureAwait(false); - ref FileStatisticsData data = ref Unsafe.As(ref statResult[0]); + scoped ref FileStatisticsData data = ref Unsafe.As(ref statResult[0]); return new FileStatistics(data); #endif } @@ -704,7 +704,7 @@ protected async Task ReadStatisticsV2Async(CancellationToken c #else byte[] statResult = new byte[FileStatisticsDataEx.Length]; _ = await Socket.ReadAsync(statResult, cancellationToken).ConfigureAwait(false); - ref FileStatisticsDataEx data = ref Unsafe.As(ref statResult[0]); + scoped ref FileStatisticsDataEx data = ref Unsafe.As(ref statResult[0]); return new FileStatisticsEx(data); #endif } diff --git a/AdvancedSharpAdbClient/SyncService.cs b/AdvancedSharpAdbClient/SyncService.cs index 283fa4c..af96759 100644 --- a/AdvancedSharpAdbClient/SyncService.cs +++ b/AdvancedSharpAdbClient/SyncService.cs @@ -146,7 +146,7 @@ public void Reopen() } /// - public virtual void Push(Stream stream, string remotePath, UnixFileStatus permission, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, in bool isCancelled = false) + public virtual void Push(Stream stream, string remotePath, UnixFileStatus permission, DateTimeOffset timestamp, Action? callback = null, bool useV2 = false, scoped in bool isCancelled = false) { if (IsProcessing) { throw new InvalidOperationException($"The {nameof(SyncService)} is currently processing a request. Please {nameof(Clone)} a new {nameof(ISyncService)} or wait until the process is finished."); } @@ -253,7 +253,7 @@ public virtual void Push(Stream stream, string remotePath, UnixFileStatus permis } /// - public virtual void Pull(string remoteFilePath, Stream stream, Action? callback = null, bool useV2 = false, in bool isCancelled = false) + public virtual void Pull(string remoteFilePath, Stream stream, Action? callback = null, bool useV2 = false, scoped in bool isCancelled = false) { if (IsProcessing) { throw new InvalidOperationException($"The {nameof(SyncService)} is currently processing a request. Please {nameof(Clone)} a new {nameof(ISyncService)} or wait until the process is finished."); } @@ -515,14 +515,14 @@ Socket is ICloneable cloneable protected FileStatistics ReadStatistics() { #if COMP_NETSTANDARD2_1 - Span statResult = stackalloc byte[FileStatisticsData.Length]; + scoped Span statResult = stackalloc byte[FileStatisticsData.Length]; _ = Socket.Read(statResult); FileStatisticsData data = EnumerableBuilder.FileStatisticsDataCreator(statResult); return new FileStatistics(data); #else byte[] statResult = new byte[FileStatisticsData.Length]; _ = Socket.Read(statResult); - ref FileStatisticsData data = ref Unsafe.As(ref statResult[0]); + scoped ref FileStatisticsData data = ref Unsafe.As(ref statResult[0]); return new FileStatistics(data); #endif } @@ -534,14 +534,14 @@ protected FileStatistics ReadStatistics() protected FileStatisticsEx ReadStatisticsV2() { #if COMP_NETSTANDARD2_1 - Span statResult = stackalloc byte[FileStatisticsDataEx.Length]; + scoped Span statResult = stackalloc byte[FileStatisticsDataEx.Length]; _ = Socket.Read(statResult); FileStatisticsDataEx data = EnumerableBuilder.FileStatisticsDataV2Creator(statResult); return new FileStatisticsEx(data); #else byte[] statResult = new byte[FileStatisticsDataEx.Length]; _ = Socket.Read(statResult); - ref FileStatisticsDataEx data = ref Unsafe.As(ref statResult[0]); + scoped ref FileStatisticsDataEx data = ref Unsafe.As(ref statResult[0]); return new FileStatisticsEx(data); #endif } diff --git a/AdvancedSharpAdbClient/TcpSocket.cs b/AdvancedSharpAdbClient/TcpSocket.cs index c27b652..33762a1 100644 --- a/AdvancedSharpAdbClient/TcpSocket.cs +++ b/AdvancedSharpAdbClient/TcpSocket.cs @@ -120,11 +120,11 @@ public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags) #if HAS_BUFFERS /// - public int Send(ReadOnlySpan buffer, SocketFlags socketFlags) => + public int Send(scoped ReadOnlySpan buffer, SocketFlags socketFlags) => Socket.Send(buffer, socketFlags); /// - public int Receive(Span buffer, SocketFlags socketFlags) => + public int Receive(scoped Span buffer, SocketFlags socketFlags) => Socket.Receive(buffer, socketFlags); #endif @@ -134,7 +134,7 @@ public int Receive(Span buffer, SocketFlags socketFlags) => /// public override string ToString() { - DefaultInterpolatedStringHandler handler = new(33, 1); + scoped DefaultInterpolatedStringHandler handler = new(33, 1); handler.AppendLiteral("The "); handler.AppendFormatted(GetType()); diff --git a/Directory.Build.props b/Directory.Build.props index 8a3b2cc..3666d85 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -23,7 +23,7 @@ https://github.com/SharpAdb/AdvancedSharpAdbClient snupkg .NET client for adb, Android Debug Bridge (AdvancedSharpAdbClient) - 3.6.16 + 3.7.17 diff --git a/Directory.Build.targets b/Directory.Build.targets index ed5ce60..c2156f2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,7 @@  - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/README.md b/README.md index 44ef31d..ba3fbea 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,6 @@ if (!AdbServer.Instance.GetStatus().IsRunning) ### Connecting to device Before using all the methods, you must initialize the new AdbClient class and then connect to the device -If you want to automate 2 or more devices at the same time, you must remember: 1 device - 1 AdbClient class - You can look at the examples to understand more ```cs diff --git a/global.json b/global.json deleted file mode 100644 index f3cb0dc..0000000 --- a/global.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "msbuild-sdks": { - "MSBuild.Sdk.Extras": "3.0.44" - } -} \ No newline at end of file