Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 224 additions & 10 deletions ADB.cs

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions AndroidSideloader.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@
<Reference Include="AdvancedSharpAdbClient, Version=3.5.15.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\AdvancedSharpAdbClient.3.5.15\lib\net45\AdvancedSharpAdbClient.dll</HintPath>
</Reference>
<Reference Include="BouncyCastle.Cryptography">
<HintPath>packages\BouncyCastle.Cryptography.2.4.0\lib\net461\BouncyCastle.Cryptography.dll</HintPath>
</Reference>
<Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath>
</Reference>
Expand All @@ -151,9 +154,15 @@
<Reference Include="Microsoft.Web.WebView2.Wpf, Version=1.0.2478.35, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Web.WebView2.1.0.2478.35\lib\net45\Microsoft.Web.WebView2.Wpf.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces">
<HintPath>packages\Microsoft.Bcl.AsyncInterfaces.1.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Renci.SshNet">
<HintPath>packages\SSH.NET.2024.2.0\lib\net462\Renci.SshNet.dll</HintPath>
</Reference>
<Reference Include="SergeUtils">
<HintPath>.\SergeUtils.dll</HintPath>
</Reference>
Expand All @@ -166,9 +175,30 @@
<Reference Include="System.IO.Compression" />
<Reference Include="System.Management" />
<Reference Include="System.Numerics" />
<Reference Include="System.Buffers">
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Formats.Asn1">
<HintPath>packages\System.Formats.Asn1.8.0.1\lib\net462\System.Formats.Asn1.dll</HintPath>
</Reference>
<Reference Include="System.Memory">
<HintPath>packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics.Vectors">
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe">
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions">
<HintPath>packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple">
<HintPath>packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
Expand All @@ -184,6 +214,10 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ADB.cs" />
<Compile Include="SFTP.cs" />
<Compile Include="SftpCredentialsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AdbCommandForm.cs">
<SubType>Form</SubType>
</Compile>
Expand Down Expand Up @@ -278,6 +312,10 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\ApiKey.cs" />
<Compile Include="SelectFolder.cs" />
<Compile Include="TransferQueue.cs" />
<Compile Include="TransferStrip.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Utilities\SettingsManager.cs" />
<Compile Include="Utilities\StringUtilities.cs" />
<Compile Include="Utilities\GeneralUtilities.cs" />
Expand Down
15 changes: 14 additions & 1 deletion FlexibleMessageBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -843,10 +843,23 @@ public static DialogResult Show(IWin32Window owner, string text, string caption,
{
FlexibleMessageBoxForm flexibleMessageBoxForm = new FlexibleMessageBoxForm
{
ShowInTaskbar = false,
// Show in the taskbar and keep the prompt above other windows so it can
// never hide behind another app (e.g. a browser/IDE) and leave the disabled
// main window looking "frozen" while it silently waits for an answer.
ShowInTaskbar = true,
TopMost = true,
CaptionText = caption,
MessageText = text
};
flexibleMessageBoxForm.Shown += (s, e) =>
{
try
{
flexibleMessageBoxForm.BringToFront();
flexibleMessageBoxForm.Activate();
}
catch { }
};
flexibleMessageBoxForm.FlexibleMessageBoxFormBindingSource.DataSource = flexibleMessageBoxForm;
flexibleMessageBoxForm.titleLabel.Text = caption;

Expand Down
80 changes: 68 additions & 12 deletions MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public partial class MainForm : Form
#endif
private readonly ListViewColumnSorter lvwColumnSorter;
private static readonly SettingsManager settings = SettingsManager.Instance;
private bool _sftpCredsPrompted = false;
private double _totalQueueSizeMB = 0;
private double _effectiveQueueSizeMB = 0;
private Dictionary<string, double> _queueEffectiveSizes = new Dictionary<string, double>(StringComparer.OrdinalIgnoreCase);
Expand Down Expand Up @@ -90,6 +91,7 @@ public partial class MainForm : Form
private const int TILE_SPACING = 10;
private string freeSpaceText = "";
private string freeSpaceTextDetailed = "";
private TransferStrip _transferStrip;
private int _questStorageProgress = 0;
private Color _mirrorPillColor = Color.FromArgb(32, 36, 44);
private DateTime _mirrorMenuClosedAt = DateTime.MinValue;
Expand Down Expand Up @@ -440,13 +442,15 @@ private async void Form1_Load(object sender, EventArgs e)
{
_ = Logger.Log("Starting AndroidSideloader Application");

// Hard kill any lingering adb.exe instances to avoid port/handle conflicts
KillAdbProcesses();

// ADB initialization in background
// Reuse an already-running adb server instead of killing it. A hard kill would
// tear down any active wireless (adb connect) session and force a reconnect that
// often fails silently. start-server is a no-op when a compatible server is already
// up, so the existing server - and any connected device, wired or wireless - is
// preserved. (Both the bundled adb and any adb in PATH are the same version now, so
// there is no version-mismatch bounce to guard against.)
_adbInitTask = Task.Run(() =>
{
_ = Logger.Log("Attempting to Initialize ADB Server");
_ = Logger.Log("Initializing ADB server (reusing existing if already running)");
if (File.Exists(Path.Combine(Environment.CurrentDirectory, "platform-tools", "adb.exe")))
{
_ = ADB.RunAdbCommandToString("start-server");
Expand All @@ -464,6 +468,11 @@ private async void Form1_Load(object sender, EventArgs e)
speedLabel.Text = String.Empty;
diskLabel.Text = String.Empty;

// Integrated transfer strip: overlays the bottom of the games list while files
// are moving (SFTP / push), themed to match the list, and hides itself when idle.
_transferStrip = new TransferStrip(gamesListView.BackColor, gamesListView.ForeColor);
_transferStrip.AttachTo(this, gamesListView);

settings.MainDir = Environment.CurrentDirectory;
settings.Save();

Expand Down Expand Up @@ -1093,7 +1102,9 @@ public async Task<int> CheckForDevice()
{
Devices.Clear();
ADB.DeviceID = GetDeviceID();
string output = await Task.Run(() => ADB.RunAdbCommandToString("devices").Output); // Run off UI thread
// Resilient: rides through an adb daemon restart so a version-mismatch server
// bounce doesn't briefly clear the device and flash "No Device Connected".
string output = await Task.Run(() => ADB.GetDevicesResilient().Output); // Run off UI thread

string[] line = output.Split('\n');
int i = 0;
Expand Down Expand Up @@ -1243,9 +1254,42 @@ public void changeTitlebarToDevice()
}
else if (Devices.Count > 0 && Devices[0].Length > 1) // Check if Devices list is not empty and the first device has a valid length
{
this.Invoke(() => { Text = "Rookie Sideloader " + Updater.LocalVersion + " | Device Connected: " + Devices[0].Replace("device", String.Empty).Trim(); });
string deviceTitle = "Rookie Sideloader " + Updater.LocalVersion + " | Device Connected: " + Devices[0].Replace("device", String.Empty).Trim();
this.Invoke(() => { Text = deviceTitle; });
DeviceConnected = true;
nodeviceonstart = false; // Device connected, clear the flag

// Detect root + SFTP availability in the background and reflect it in the titlebar
_ = Task.Run(async () =>
{
await SFTP.DetectAsync(force: true);
try
{
this.Invoke(() => { Text = deviceTitle + SFTP.TitleSuffix; });

// A server answered but our credentials didn't work: ask the user
// (once per session) for a password or key file, then retry
if (!SFTP.IsSftpAvailable && SFTP.AuthFailedButServerPresent
&& settings.EnableSftpTransfers && !_sftpCredsPrompted)
{
_sftpCredsPrompted = true;
bool retry = false;
this.Invoke(() =>
{
using (SftpCredentialsForm dialog = new SftpCredentialsForm())
{
retry = dialog.ShowDialog(this) == DialogResult.OK;
}
});
if (retry)
{
await SFTP.DetectAsync(force: true);
this.Invoke(() => { Text = deviceTitle + SFTP.TitleSuffix; });
}
}
}
catch { }
});
}
else
{
Expand Down Expand Up @@ -7846,18 +7890,30 @@ public async void UpdateQuestInfoPanel()
{
try
{
ADB.DeviceID = GetDeviceID();
// Fetch device info OFF the UI thread. These adb shell calls can block for
// tens of seconds if the adb server is mid-restart (e.g. a version-mismatched
// adb elsewhere bounces the daemon); running them here would freeze the whole UI.
var info = await Task.Run(() =>
{
ADB.DeviceID = GetDeviceID();
return new
{
Model = ADB.RunAdbCommandToString("shell getprop ro.product.model").Output.Trim(),
Firmware = ADB.RunAdbCommandToString("shell getprop ro.build.branch").Output.Trim(),
Storage = ADB.RunAdbCommandToString("shell df /data").Output
};
});

// Get device model
string deviceModel = ADB.RunAdbCommandToString("shell getprop ro.product.model").Output.Trim();
string deviceModel = info.Model;
if (string.IsNullOrEmpty(deviceModel))
{
deviceModel = "No Device Found";
SetQuestStorageProgress(0);
bShowStatus = false;
}

string firmware = ADB.RunAdbCommandToString("shell getprop ro.build.branch").Output.Trim(); // releases-oculus-14.0-v78
string firmware = info.Firmware; // releases-oculus-14.0-v78
if (string.IsNullOrEmpty(firmware))
{
firmware = string.Empty;
Expand All @@ -7869,7 +7925,7 @@ public async void UpdateQuestInfoPanel()
}

// Get storage info
string storageOutput = ADB.RunAdbCommandToString("shell df /data").Output;
string storageOutput = info.Storage;
string[] lines = storageOutput.Split('\n');

long totalSpace = 0;
Expand Down Expand Up @@ -10214,7 +10270,7 @@ private async void timer_DeviceCheck(object sender, EventArgs e)
// Run a quick device check in background
try
{
string output = await Task.Run(() => ADB.RunAdbCommandToString("devices", suppressLogging: true).Output);
string output = await Task.Run(() => ADB.GetDevicesResilient().Output);

string[] lines = output.Split('\n');
bool hasDeviceNow = false;
Expand Down
Loading