private void InitAutumnBoxBasic() { Basic.Util.Settings.CreateNewWindow = Settings.Default.DisplayCmdWindow; try { logger.Info("killing other adb processes"); TaskKill.Kill("adb.exe"); logger.Info("autumnbox-adb-server is starting"); var adbManager = AdbProviderFactory.Get(true).AdbManager; Adb.Load(adbManager); Adb.Server.Start(); logger.Info($"autumnbox-adb-server is started at {Adb.Server.IP}:{Adb.Server.Port}"); } catch (Exception e) { logger.Warn("there's some error happened while starting autumnbox-adb-server", e); App.Current.Dispatcher.Invoke(() => { new AdbFailedWindow(e.Message) { Owner = App.Current.MainWindow }.ShowDialog(); }); Fail(); } }
public async Task GetDevicesAllStates() { // arrange var output = new List <string> { "List of devices attached", "PHILIPS W732\tdevice", "0123456789ABCDE\tunauthorized", "0123456789ABCDE\toffline" }; var processManager = new TestProcessManager(); processManager.AddProcess(output); var adb = new Adb(processManager); // act var devices = (await adb.GetDevices()).ToList(); // assert processManager.Stub.AssertWasCalled(_ => _.CreateProcess(Arg <string> .Is.Anything, Arg <string> .Matches(commands => commands.Contains("devices")))); Assert.AreEqual(3, devices.Count); Assert.IsTrue(devices.ElementAt(0).State == DeviceState.Online); Assert.IsTrue(devices.ElementAt(1).State == DeviceState.Unauthorized); Assert.IsTrue(devices.ElementAt(2).State == DeviceState.Offline); }
private void apk_Click(object sender, RoutedEventArgs e) { AndroidController a = AndroidController.Instance; string caminho = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\SGEA\\SGEA.SGEA.apk"; if (a.HasConnectedDevices) { caminho = "\"" + caminho + "\""; Device d = a.GetConnectedDevice(a.ConnectedDevices[0]); for (int i = 0; i < a.ConnectedDevices.Count; i++) { d = a.GetConnectedDevice(a.ConnectedDevices[i]); if (!d.SerialNumber.Contains("emulator")) { break; } } var ad = Adb.FormAdbShellCommand(d, false, "pm list packages SGEA.SGEA"); string x = Adb.ExecuteAdbCommand(ad); if (x != "package:SGEA.SGEA") { var ade = Adb.FormAdbCommand(d, "install " + caminho); Adb.ExecuteAdbCommand(ade); Xceed.Wpf.Toolkit.MessageBox.Show("O aplicativo foi instalado com sucesso"); } else { Xceed.Wpf.Toolkit.MessageBox.Show("O aplicativo já está instalado"); } } else { Xceed.Wpf.Toolkit.MessageBox.Show("Não há um celular Android conectado por USB"); } }
async Task Download() { var appData = Directory.CreateDirectory(adbDirectory); adb = new Adb(appData); //Check if exists in new Dirctory if (await IsAdbSetup()) { return; } var adbZipPAth = Path.Combine(tempDirectory, "adb.zip"); try { var client = new WebClient(); await Task.Run(() => client.DownloadFile(new Uri("https://adbshell.com/upload/adb.zip"), adbZipPAth)); Directory.CreateDirectory(platformToolsDirectory); System.IO.Compression.ZipFile.ExtractToDirectory(adbZipPAth, platformToolsDirectory); //sdkManager = new Adb(appData); var success = await IsAdbSetup(); } catch (Exception ex) { } finally { if (File.Exists(adbZipPAth)) { File.Delete(adbZipPAth); } } //Lets download it! }
public async Task CreateUser_Error() { //arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "Error: couldn't create User." }, "create-user"); var adb = new Adb(processManager); //act try { await adb.SingleDevice.Shell.PackageManager.CreateUser("Test"); //assert Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOf <AdbException>(ex); } }
private void InitAutumnBoxBasic() { Basic.Util.Settings.CreateNewWindow = Settings.Default.DisplayCmdWindow; try { TaskKill.Kill("adb.exe"); logger.Info("adb server starting"); var adbManager = new ATMBWin32AdbManager(); adbManager.Extract(); Adb.Load(adbManager); Adb.Server.Start(); logger.Info($"adb server started at {Adb.Server.IP}:{Adb.Server.Port}"); } catch (Exception e) { logger.Warn("can not start adb server!", e); App.Current.Dispatcher.Invoke(() => { new AdbFailedWindow(e.Message) { Owner = App.Current.MainWindow }.ShowDialog(); }); Fail(); } }
public override int Execute([NotNull] CommandContext context, [NotNull] DevicesListCommandSettings settings) { try { var adb = new Adb(settings?.Home); var devices = adb.GetDevices(); if ((settings?.Format ?? OutputFormat.None) == OutputFormat.None) { OutputHelper.OutputTable( devices, new[] { "Serial", "Emulator", "Device", "Model", "Product" }, i => new[] { i.Serial, i.IsEmulator.ToString(), i.Device, i.Model, i.Product }); } else { OutputHelper.Output(devices, settings.Format); } } catch (SdkToolFailedExitException sdkEx) { Program.WriteException(sdkEx); return(1); } return(0); }
/// <summary> /// Dials (does not call) a phone number on the Android device /// </summary> /// <param name="phoneNumber">Phone number to dial</param> public void DialPhoneNumber(string phoneNumber) { if (this.device.State != DeviceState.ONLINE) return; AdbCommand adbCmd = Adb.FormAdbShellCommand(this.device, false, "service", "call", "phone", "1", "s16", phoneNumber); Adb.ExecuteAdbCommandNoReturn(adbCmd); }
private void Load() { LoggingStation.Instance.Work(); Updater.CheckAndNotice(); Statistics.Do(); ui.Progress = 0; //如果设置在启动时打开调试窗口 if (Settings.Default.ShowDebuggingWindowNextLaunch) { //打开调试窗口 App.Current.Dispatcher.Invoke(() => { new LogWindow().Show(); }); } logger.Info(""); logger.Info("======================"); logger.Info($"Run as " + (Self.HaveAdminPermission ? "Admin" : "Normal user")); logger.Info($"AutumnBox version: {Self.Version}"); logger.Info($"SDK version: {BuildInfo.SDK_VERSION}"); logger.Info($"Windows version {Environment.OSVersion.Version}"); logger.Info("======================"); logger.Info("===loading==="); #if DEBUG Basic.Util.Debugging.LoggingStation.Logging += (s, e) => { LoggingStation.Instance.Log(e.Tag, e.Level.ToString(), e.Text); }; #endif ui.Progress = 30; ui.LoadingTip = App.Current.Resources["ldmsgStartAdb"].ToString(); try { logger.Info("trying starts adb server "); Adb.DefaultLoad(); logger.Info("adb server starts successed"); } catch (AdbCommandFailedException e) { logger.Info("adb server starts failed"); logger.Warn(e); ui.Progress = 60; ui.LoadingTip = App.Current.Resources["ldmsgAdbServerFailed"].ToString(); Thread.Sleep(10000); App.Current.Shutdown(e.ExitCode); } ui.Progress = 60; ui.LoadingTip = App.Current.Resources["ldmsgLoadingExtensions"].ToString(); OpenFrameworkManager.Init(); OpenFxObserver.Instance.OnLoaded(); ConnectedDevicesListener.Instance.Work(); ui.Progress = 100; ui.LoadingTip = "Enjoy!"; Thread.Sleep(1 * 1000); logger.Info("===loaded==="); ui.Finish(); }
public async void OnConnectionEvent(object sender, ConnectionEventArgs e) { if (e.NewState == ConnectionEventArgs.EState.DISCONNECTED) { await Adb.StopScreenCappingAsync(); ScreenCapAdjustLayout(false); } }
public void Update() { if (_device.State == DeviceState.ONLINE) { _root = Adb.ExecuteAdbCommand(Adb.FormAdbShellCommand(_device, false, "su", "-v")); _busybox = Adb.ExecuteAdbCommand(Adb.FormAdbShellCommand(_device, false, "busybox")); _getprop = Adb.ExecuteAdbCommand(Adb.FormAdbShellCommand(_device, false, "getprop")); } }
/// <summary> /// Calls a phone number on the Android device /// </summary> /// <param name="phoneNumber">Phone number to call</param> public void CallPhoneNumber(string phoneNumber) { if (this.device.State != DeviceState.ONLINE) return; AdbCommand adbCmd = Adb.FormAdbShellCommand(this.device, false, "service", "call", "phone", "2", "s16", phoneNumber); Adb.ExecuteAdbCommandNoReturn(adbCmd); adbCmd = Adb.FormAdbShellCommand(this.device, false, "input", "keyevent", (int)KeyEventCode.BACK); Adb.ExecuteAdbCommandNoReturn(adbCmd); }
public async Task GetState(string[] output, AdbState state) { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(output); var adb = new Adb(processManager); var result = await adb.GetState(); processManager.Stub.AssertWasCalled(_ => _.CreateProcess(Arg <string> .Is.Anything, Arg <string> .Matches(commands => commands.Contains("get-state")))); Assert.IsTrue(result == state); }
/// <summary> /// Run the process. /// </summary> protected override void DoWork() { // Get APK package name var apk = new ApkFile(apkPath); var packageName = apk.Manifest.PackageName; // Now install var adb = new Adb { Logger = LogOutput }; adb.InstallApk(device.Serial, apkPath, packageName, Adb.Timeout.InstallApk); }
public override int Execute([NotNull] CommandContext context, [NotNull] DeviceInfoCommandSettings settings) { try { var adb = new Adb(settings?.Home); var devices = adb.GetDevices(); var deviceFilterSpecified = settings.Devices?.Any() ?? false; var results = new List <DeviceWrapper>(); foreach (var device in devices) { // If filtering on device, check that this is in the list if (deviceFilterSpecified && !settings.Devices.Any(d => IsPropertyMatch(device.Serial, d))) { continue; } var props = adb.GetProperties(device.Serial, settings.Properties); if (settings.Format == OutputFormat.None) { var rule = new Rule(device.Serial); AnsiConsole.Render(rule); OutputHelper.OutputTable(props, new[] { "Property Name", "Property Value" }, i => new[] { i.Key, i.Value }); AnsiConsole.WriteLine(); } results.Add(new DeviceWrapper { Device = device, Properties = adb.GetProperties(device.Serial, settings.Properties) }); } if (settings.Format != OutputFormat.None) { OutputHelper.Output(results, settings.Format); } } catch (SdkToolFailedExitException sdkEx) { Program.WriteException(sdkEx); return(1); } return(0); }
/// <summary> /// Perform the action. /// </summary> protected override void DoWork() { // Listen for devices deviceMonitor.Start(); deviceMonitor.WaitForInitialUpdate(); // Perform the connect connecting = true; var adb = new Adb { Logger = LogOutput }; adb.Connect(host, port, Adb.Timeout.Connect); }
public async Task GetPropertyNull() { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { " " }); var adb = new Adb(processManager); // act var result = await adb.SingleDevice.Shell.GetProperty("test.property"); // assert Assert.IsNull(result); }
private void buttonRebootRecovery_Click(object sender, EventArgs e) { if (isConnected()) { cAppend("Rebooting into recovery..."); Adb.ExecuteAdbCommand(Adb.FormAdbCommand(" reboot recovery")); cAppend("Rebooting into recovery... {OK}"); } else { cAppend("{RebootRecovery} Please connect your device..."); return; } }
private static async Task ConfigureForAndroidTests(TestConfiguration config, int?androidSdk, string headBin, CancellationToken cancellationToken) { // Ensure WebDrivers are installed await SdkManager.InstallWebDriver(cancellationToken).ConfigureAwait(false); // Ensure latest CmdLine tools are installed await SdkManager.InstallLatestCommandLineTools(cancellationToken).ConfigureAwait(false); var sdkVersion = ApkHelper.GetAndroidSdkVersion(androidSdk, headBin); Logger.WriteLine($"Targeting Android Sdk: {sdkVersion}", LogLevel.Minimal); var appActivity = ApkHelper.GetAppActivity(headBin); if (!config.Capabilities.ContainsKey("appActivity")) { config.Capabilities.Add("appActivity", appActivity); } var emulatorName = $"{AvdManager.DefaultUITestEmulatorName}{sdkVersion}"; // Check for connected device if (await Adb.DeviceIsConnected(cancellationToken)) { var androidDevice = (await Adb.ListDevices(cancellationToken).ConfigureAwait(false)).First(); config.DeviceName = androidDevice.Name; config.UDID = androidDevice.Id; config.OSVersion = $"{androidDevice.SdkVersion}"; } else { // Ensure SDK Installed await SdkManager.EnsureSdkIsInstalled(sdkVersion, cancellationToken).ConfigureAwait(false); // Ensure Emulator Exists if (!(await Emulator.ListEmulators(cancellationToken)).Any(x => x == emulatorName)) { await AvdManager.InstallEmulator(emulatorName, sdkVersion, cancellationToken); } // Let Appium Start and control the Emulator config.DeviceName = emulatorName; config.OSVersion = $"{sdkVersion}"; if (!config.Capabilities.ContainsKey("avd")) { config.Capabilities.Add("avd", emulatorName); } } }
public async Task InstallWithInstaller() { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "Success" }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleDevice; await deviceAdb.Install("test.apk", InstallOptions.None, "com.android.vending"); // assert processManager.Stub.AssertWasCalled(_ => _.CreateProcess(Arg <string> .Is.Anything, Arg <string> .Matches(c => c.Contains("-i com.android.vending")))); }
public async Task Install(InstallOptions options, string expected) { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "Success" }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleDevice; await deviceAdb.Install("test.apk", options); // assert processManager.Stub.AssertWasCalled(_ => _.CreateProcess(Arg <string> .Is.Anything, Arg <string> .Matches(c => c.Contains(expected)))); }
public async Task SingleEmulator() { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "Some output" }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleEmulator; await deviceAdb.RunCommand("test"); // assert processManager.Stub.AssertWasCalled(_ => _.CreateProcess(Arg <string> .Is.Anything, Arg <string> .Matches(commands => commands.Contains("-e test")))); }
public async Task InstallResult(string output, string expected) { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "3584 KB/s (69747 bytes in 0.019s)", " pkg: /data/local/tmp/LocaleChanger.apk", output }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleDevice; var result = await deviceAdb.Install("test.apk"); // assert Assert.AreEqual(expected, result); }
private void bd_Click(object sender, RoutedEventArgs e) { AndroidController a = AndroidController.Instance; string c = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\SGEA\\sgea.db"; string imagens = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\SGEA\\Imagens"; if (File.Exists(c)) { if (a.HasConnectedDevices) { c = "\"" + c + "\""; imagens = "\"" + imagens + "\""; Device d = a.GetConnectedDevice(a.ConnectedDevices[0]); for (int i = 0; i < a.ConnectedDevices.Count; i++) { d = a.GetConnectedDevice(a.ConnectedDevices[i]); if (!d.SerialNumber.Contains("emulator")) { break; } } var ad = Adb.FormAdbShellCommand(d, false, "rmdir -r sdcard/SGEA"); Adb.ExecuteAdbCommand(ad); ad = Adb.FormAdbShellCommand(d, false, "mkdir sdcard/SGEA"); Adb.ExecuteAdbCommand(ad); ad = Adb.FormAdbShellCommand(d, false, "mkdir sdcard/SGEA/Imagens"); Adb.ExecuteAdbCommand(ad); bool b = d.PushFile(c, "sdcard/SGEA", 100000); bool f = d.PushFile(imagens, "sdcard/SGEA/Imagens/", 100000); if (b && f) { Xceed.Wpf.Toolkit.MessageBox.Show("Banco de Dados foi transferido com sucesso"); } else { Xceed.Wpf.Toolkit.MessageBox.Show("Banco de Dados não foi transferido"); } } else { Xceed.Wpf.Toolkit.MessageBox.Show("Não há um celular Android conectado por USB"); } } else { Xceed.Wpf.Toolkit.MessageBox.Show("O banco de dados não existe. \nPor favor, entre em contato conosco"); } }
public async Task FailPullResult() { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "adb: error: remote object '/mnt/sdcard/Log2.txt' does not exist" }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleDevice; var result = await deviceAdb.Pull("/mnt/sdcard/", "Log.txt"); // assert Assert.IsFalse(result.Success); Assert.AreEqual("remote object '/mnt/sdcard/Log2.txt' does not exist", result.Error); }
public async Task TargetDevice() { // arrange const string id = "Device ID"; var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "Some output" }); var adb = new Adb(processManager); // act var deviceAdb = adb.Target(id); await deviceAdb.RunCommand("test"); // assert processManager.Stub.AssertWasCalled(_ => _.CreateProcess(Arg <string> .Is.Anything, Arg <string> .Matches(commands => commands.Contains(String.Format("-s \"{0}\" test", id))))); }
public async Task FailPushResult2() { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "adb: error: failed to copy 'Log.txt' to '/mnt/rtyrtyurt': Read-only file system" }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleDevice; var result = await deviceAdb.Pull("/mnt/rtyrtyurt", "Log.txt"); // assert Assert.IsFalse(result.Success); Assert.AreEqual("Read-only file system", result.Error); }
public async Task FailPushResult() { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "adb: error: failed to copy 'Log.txt' to '/mnt/sdcard2/Log.txt': Permission denied" }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleDevice; var result = await deviceAdb.Pull("/mnt/sdcard/", "Log.txt"); // assert Assert.IsFalse(result.Success); Assert.AreEqual("Permission denied", result.Error); }
public async Task SuccessPushResult() { // arrange var processManager = new TestProcessManager(); processManager.AddProcess(new[] { "[100%] /mnt/sdcard/Log.txt" }); var adb = new Adb(processManager); // act var deviceAdb = adb.SingleDevice; var result = await deviceAdb.Push("Log.txt", "/mnt/sdcard/"); // assert Assert.IsTrue(result.Success); Assert.IsNull(result.Error); }
private async void ScreenCapImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (ScreenCapture == Adb && Adb.IsScreenCapActive && !Adb.IsScreenCapOutOfDate && Properties.Settings.Default.ScreenCapEnableTap && Adb.CurrentScreenCap != null) { Image scImage = sender as Image; if (scImage == null) { return; } Point point = e.MouseDevice.GetPosition((FrameworkElement)sender); point.X *= Adb.CurrentScreenCap.Width / scImage.ActualWidth; point.Y *= Adb.CurrentScreenCap.Height / scImage.ActualHeight; e.Handled = true; await Adb.DoTapAsync(point); } }
private LocalLaunchOptions SetupForDebuggingWorker(CancellationToken token) { CancellationTokenRegistration onCancelRegistration = token.Register(() => { _gdbServerExecCancellationSource.Cancel(); }); using (onCancelRegistration) { // TODO: Adb exception messages should be improved. Example, if ADB is not started, this is returned: // + [libadb.AdbException] {"Could not connect to the adb.exe server. See InnerException for details."} libadb.AdbException // 'See InnerException for details.' should not be there. It should just add the inner exception message: // [System.Net.Sockets.SocketException] {"No connection could be made because the target machine actively refused it 127.0.0.1:5037"} System.Net.Sockets.SocketException Device device = null; string workingDirectory = null; string gdbServerRemotePath = null; string gdbServerSocketDescription = null; Task taskGdbServer = null; int gdbPortNumber = 0; int progressCurrentIndex = 0; int progressStepCount = 0; List<NamedAction> actions = new List<NamedAction>(); actions.Add(new NamedAction(LauncherResources.Step_ResolveInstallPaths, () => { _installPaths = InstallPaths.Resolve(token, _launchOptions); })); actions.Add(new NamedAction(LauncherResources.Step_ConnectToDevice, () => { Adb adb; try { adb = new Adb(_installPaths.SDKRoot); } catch (ArgumentException) { throw new LauncherException(Telemetry.LaunchFailureCode.InvalidAndroidSDK, string.Format(CultureInfo.CurrentCulture, LauncherResources.Error_InvalidAndroidSDK, _installPaths.SDKRoot)); } try { adb.Start(); device = adb.GetDeviceById(_launchOptions.DeviceId); // There is a rare case, which we have seen it a few times now with the Android emulator where the device will be initially // in the offline state. But after a very short amount of time it comes online. Retry waiting for this. if (device.GetState().HasFlag(DeviceState.Offline)) { // Add in an extra progress step and update the dialog progressStepCount++; _waitLoop.SetProgress(progressStepCount, progressCurrentIndex, LauncherResources.Step_WaitingForDeviceToComeOnline); progressCurrentIndex++; const int waitTimePerIteration = 50; const int maxTries = 5000 / waitTimePerIteration; // We will wait for up to 5 seconds // NOTE: libadb has device discovery built in which we could allegedly use instead of a retry loop, // but I couldn't get this to work (though the problem is so rare, I had a lot of trouble testing it), so just using // a retry loop. for (int cTry = 0; true; cTry++) { if (cTry == maxTries) { throw new LauncherException(Telemetry.LaunchFailureCode.DeviceOffline, LauncherResources.Error_DeviceOffline); } // Sleep for a little while unless this operation is canceled if (token.WaitHandle.WaitOne(waitTimePerIteration)) { throw new OperationCanceledException(); } if (!device.GetState().HasFlag(DeviceState.Offline)) { break; // we are no longer offline } } } } catch (AdbException) { throw new LauncherException(Telemetry.LaunchFailureCode.DeviceNotResponding, LauncherResources.Error_DeviceNotResponding); } })); actions.Add(new NamedAction(LauncherResources.Step_InspectingDevice, () => { try { DeviceAbi deviceAbi = device.Abi; if (deviceAbi == DeviceAbi.unknown) deviceAbi = device.Abi2; switch (_launchOptions.TargetArchitecture) { case TargetArchitecture.ARM: if (deviceAbi != DeviceAbi.armeabi && deviceAbi != DeviceAbi.armeabiv7a) { throw GetBadDeviceAbiException(deviceAbi); } break; case TargetArchitecture.X86: if (deviceAbi != DeviceAbi.x86) { throw GetBadDeviceAbiException(deviceAbi); } break; default: Debug.Fail("New target architucture support added without updating this code???"); throw new InvalidOperationException(); } if (_launchOptions.TargetArchitecture == TargetArchitecture.ARM && device.IsEmulator) { _isUsingArmEmulator = true; } _shell = device.Shell; } catch (AdbException) { throw new LauncherException(Telemetry.LaunchFailureCode.DeviceNotResponding, LauncherResources.Error_DeviceNotResponding); } VerifySdkVersion(); string pwdCommand = string.Concat("run-as ", _launchOptions.Package, " /system/bin/sh -c pwd"); ExecCommand(pwdCommand); workingDirectory = ParsePwdOutput(_shell.Out); // Kill old processes to make sure we aren't confused and think an old process is still arround gdbServerRemotePath = workingDirectory + "/lib/gdbserver"; KillOldInstances(gdbServerRemotePath); string lsCommand = string.Format(CultureInfo.InvariantCulture, "ls {0}", gdbServerRemotePath); string output = ExecCommand(lsCommand); if (string.Compare(output, gdbServerRemotePath, StringComparison.OrdinalIgnoreCase) != 0) { throw new LauncherException(Telemetry.LaunchFailureCode.NoGdbServer, string.Format(CultureInfo.CurrentCulture, LauncherResources.Error_NoGdbServer, gdbServerRemotePath)); } })); if (!_launchOptions.IsAttach) { actions.Add(new NamedAction(LauncherResources.Step_StartingApp, () => { string activateCommand = string.Concat("am start -D -n ", _launchOptions.Package, "/", _launchOptions.LaunchActivity); ExecCommand(activateCommand); ValidateActivityManagerOutput(activateCommand, _shell.Out); })); } actions.Add(new NamedAction(LauncherResources.Step_GettingAppProcessId, () => { _appProcessId = GetAppProcessId(); })); actions.Add(new NamedAction(LauncherResources.Step_StartGDBServer, () => { // We will default to using a unix socket with gdbserver as this is what the ndk-gdb script uses. Though we have seen // some machines where this doesn't work and we fall back to TCP instead. const bool useUnixSocket = true; taskGdbServer = StartGdbServer(gdbServerRemotePath, workingDirectory, useUnixSocket, out gdbServerSocketDescription); })); actions.Add(new NamedAction(LauncherResources.Step_PortForwarding, () => { // TODO: Use a dynamic socket gdbPortNumber = 5039; _jdbPortNumber = 65534; device.Forward(string.Format(CultureInfo.InvariantCulture, "tcp:{0}", gdbPortNumber), gdbServerSocketDescription); if (!_launchOptions.IsAttach) { device.Forward(string.Format(CultureInfo.InvariantCulture, "tcp:{0}", _jdbPortNumber), string.Format(CultureInfo.InvariantCulture, "jdwp:{0}", _appProcessId)); } })); actions.Add(new NamedAction(LauncherResources.Step_DownloadingFiles, () => { //pull binaries from the emulator/device var fileSystem = device.FileSystem; fileSystem.Download(@"/system/bin/app_process", Path.Combine(_launchOptions.IntermediateDirectory, "app_process"), true); fileSystem.Download(@"/system/bin/linker", Path.Combine(_launchOptions.IntermediateDirectory, "linker"), true); fileSystem.Download(@"/system/lib/libc.so", Path.Combine(_launchOptions.IntermediateDirectory, "libc.so"), true); })); progressStepCount = actions.Count; foreach (NamedAction namedAction in actions) { token.ThrowIfCancellationRequested(); _waitLoop.SetProgress(progressStepCount, progressCurrentIndex, namedAction.Name); progressCurrentIndex++; namedAction.Action(); } _waitLoop.SetProgress(progressStepCount, progressStepCount, string.Empty); if (taskGdbServer.IsCompleted) { token.ThrowIfCancellationRequested(); throw new LauncherException(Telemetry.LaunchFailureCode.GDBServerFailed, LauncherResources.Error_GDBServerFailed); } if (_launchOptions.LogcatServiceId != Guid.Empty) { _eventCallback.OnCustomDebugEvent(_launchOptions.LogcatServiceId, new Guid(LogcatServiceMessage_SourceId), LogcatServiceMessage_NewProcess, _appProcessId, null); } var launchOptions = new LocalLaunchOptions(_installPaths.GDBPath, string.Format(CultureInfo.InvariantCulture, ":{0}", gdbPortNumber)); launchOptions.AdditionalSOLibSearchPath = _launchOptions.AdditionalSOLibSearchPath; launchOptions.TargetArchitecture = _launchOptions.TargetArchitecture; launchOptions.WorkingDirectory = _launchOptions.IntermediateDirectory; launchOptions.ExePath = Path.Combine(_launchOptions.IntermediateDirectory, "app_process"); launchOptions.DebuggerMIMode = MIMode.Gdb; launchOptions.VisualizerFile = "Microsoft.Android.natvis"; return launchOptions; } }
private LaunchOptions SetupForDebuggingWorker(CancellationToken token) { CancellationTokenRegistration onCancelRegistration = token.Register(() => { _gdbServerExecCancellationSource.Cancel(); }); using (onCancelRegistration) { // TODO: Adb exception messages should be improved. Example, if ADB is not started, this is returned: // + [libadb.AdbException] {"Could not connect to the adb.exe server. See InnerException for details."} libadb.AdbException // 'See InnerException for details.' should not be there. It should just add the inner exception message: // [System.Net.Sockets.SocketException] {"No connection could be made because the target machine actively refused it 127.0.0.1:5037"} System.Net.Sockets.SocketException Device device = null; string workingDirectory = null; string gdbServerRemotePath = null; string gdbServerSocketDescription = null; string exePath = null; Task taskGdbServer = null; int gdbPortNumber = 0; int progressCurrentIndex = 0; int progressStepCount = 0; List<NamedAction> actions = new List<NamedAction>(); actions.Add(new NamedAction(LauncherResources.Step_ResolveInstallPaths, () => { _installPaths = InstallPaths.Resolve(token, _launchOptions, Logger); })); actions.Add(new NamedAction(LauncherResources.Step_ConnectToDevice, () => { Adb adb; try { adb = new Adb(_installPaths.SDKRoot); } catch (ArgumentException) { throw new LauncherException(Telemetry.LaunchFailureCode.InvalidAndroidSDK, string.Format(CultureInfo.CurrentCulture, LauncherResources.Error_InvalidAndroidSDK, _installPaths.SDKRoot)); } try { adb.Start(); device = adb.GetDeviceById(_launchOptions.DeviceId); // There is a rare case, which we have seen it a few times now with the Android emulator where the device will be initially // in the offline state. But after a very short amount of time it comes online. Retry waiting for this. if (device.GetState().HasFlag(DeviceState.Offline)) { // Add in an extra progress step and update the dialog progressStepCount++; _waitLoop.SetProgress(progressStepCount, progressCurrentIndex, LauncherResources.Step_WaitingForDeviceToComeOnline); progressCurrentIndex++; const int waitTimePerIteration = 50; const int maxTries = 5000 / waitTimePerIteration; // We will wait for up to 5 seconds // NOTE: libadb has device discovery built in which we could allegedly use instead of a retry loop, // but I couldn't get this to work (though the problem is so rare, I had a lot of trouble testing it), so just using // a retry loop. for (int cTry = 0; true; cTry++) { if (cTry == maxTries) { throw new LauncherException(Telemetry.LaunchFailureCode.DeviceOffline, LauncherResources.Error_DeviceOffline); } // Sleep for a little while unless this operation is canceled if (token.WaitHandle.WaitOne(waitTimePerIteration)) { throw new OperationCanceledException(); } if (!device.GetState().HasFlag(DeviceState.Offline)) { break; // we are no longer offline } } } } catch (AdbException) { throw new LauncherException(Telemetry.LaunchFailureCode.DeviceNotResponding, LauncherResources.Error_DeviceNotResponding); } })); actions.Add(new NamedAction(LauncherResources.Step_InspectingDevice, () => { try { DeviceAbi[] allowedAbis; switch (_launchOptions.TargetArchitecture) { case TargetArchitecture.ARM: allowedAbis = new DeviceAbi[] { DeviceAbi.armeabi, DeviceAbi.armeabiv7a }; break; case TargetArchitecture.ARM64: allowedAbis = new DeviceAbi[] { DeviceAbi.arm64v8a }; break; case TargetArchitecture.X86: allowedAbis = new DeviceAbi[] { DeviceAbi.x86 }; break; case TargetArchitecture.X64: allowedAbis = new DeviceAbi[] { DeviceAbi.x64 }; break; default: Debug.Fail("New target architucture support added without updating this code???"); throw new InvalidOperationException(); } if (!DoesDeviceSupportAnyAbi(device, allowedAbis)) { throw GetBadDeviceAbiException(device.Abi); } if (_launchOptions.TargetArchitecture == TargetArchitecture.ARM && device.IsEmulator) { _isUsingArmEmulator = true; } _shell = device.Shell; } catch (AdbException) { throw new LauncherException(Telemetry.LaunchFailureCode.DeviceNotResponding, LauncherResources.Error_DeviceNotResponding); } VerifySdkVersion(); if (_targetEngine == TargetEngine.Native) { string pwdCommand = string.Concat("run-as ", _launchOptions.Package, " /system/bin/sh -c pwd"); ExecCommand(pwdCommand); workingDirectory = PwdOutputParser.ExtractWorkingDirectory(_shell.Out, _launchOptions.Package); gdbServerRemotePath = GetGdbServerPath(workingDirectory, device); KillOldInstances(gdbServerRemotePath); } })); if (!_launchOptions.IsAttach) { actions.Add(new NamedAction(LauncherResources.Step_StartingApp, () => { string activateCommand = string.Concat("am start -D -n ", _launchOptions.Package, "/", _launchOptions.LaunchActivity); ExecCommand(activateCommand); ValidateActivityManagerOutput(activateCommand, _shell.Out); })); } actions.Add(new NamedAction(LauncherResources.Step_GettingAppProcessId, () => { _appProcessId = GetAppProcessId(); })); if (_targetEngine == TargetEngine.Native) { actions.Add(new NamedAction(LauncherResources.Step_StartGDBServer, () => { // We will default to using a unix socket with gdbserver as this is what the ndk-gdb script uses. Though we have seen // some machines where this doesn't work and we fall back to TCP instead. const bool useUnixSocket = true; taskGdbServer = StartGdbServer(gdbServerRemotePath, workingDirectory, useUnixSocket, out gdbServerSocketDescription); })); } actions.Add(new NamedAction(LauncherResources.Step_PortForwarding, () => { // TODO: Use a dynamic socket gdbPortNumber = 5039; _jdbPortNumber = 65534; if (_targetEngine == TargetEngine.Native) { device.Forward(string.Format(CultureInfo.InvariantCulture, "tcp:{0}", gdbPortNumber), gdbServerSocketDescription); } device.Forward(string.Format(CultureInfo.InvariantCulture, "tcp:{0}", _jdbPortNumber), string.Format(CultureInfo.InvariantCulture, "jdwp:{0}", _appProcessId)); })); if (_targetEngine == TargetEngine.Native) { actions.Add(new NamedAction(LauncherResources.Step_DownloadingFiles, () => { //pull binaries from the emulator/device var fileSystem = device.FileSystem; string app_process_suffix = String.Empty; switch (_launchOptions.TargetArchitecture) { case TargetArchitecture.X86: case TargetArchitecture.ARM: app_process_suffix = "32"; break; case TargetArchitecture.X64: case TargetArchitecture.ARM64: app_process_suffix = "64"; break; default: Debug.Fail("Unsupported Target Architecture!"); break; } string app_process = String.Concat("app_process", app_process_suffix); exePath = Path.Combine(_launchOptions.IntermediateDirectory, app_process); bool retry = false; try { fileSystem.Download(@"/system/bin/" + app_process, exePath, true); } catch (AdbException) when (String.Compare(app_process_suffix, "32", StringComparison.OrdinalIgnoreCase) == 0) { // Older devices don't have an 'app_process32', only an 'app_process', so retry // NOTE: libadb doesn't have an error code property to verify that this is caused // by the file not being found. retry = true; } if (retry) { app_process = "app_process"; exePath = Path.Combine(_launchOptions.IntermediateDirectory, app_process); fileSystem.Download(@"/system/bin/app_process", exePath, true); } //on 64 bit, 'linker64' is the 64bit version and 'linker' is the 32 bit version string suffix64bit = String.Empty; if (_launchOptions.TargetArchitecture == TargetArchitecture.X64 || _launchOptions.TargetArchitecture == TargetArchitecture.ARM64) { suffix64bit = "64"; } string linker = String.Concat("linker", suffix64bit); fileSystem.Download(String.Concat(@"/system/bin/", linker), Path.Combine(_launchOptions.IntermediateDirectory, linker), true); //on 64 bit, libc.so lives in /system/lib64/, on 32 bit it lives in simply /system/lib/ fileSystem.Download(@"/system/lib" + suffix64bit + "/libc.so", Path.Combine(_launchOptions.IntermediateDirectory, "libc.so"), true); })); } progressStepCount = actions.Count; foreach (NamedAction namedAction in actions) { token.ThrowIfCancellationRequested(); _waitLoop.SetProgress(progressStepCount, progressCurrentIndex, namedAction.Name); progressCurrentIndex++; namedAction.Action(); } _waitLoop.SetProgress(progressStepCount, progressStepCount, string.Empty); if (_targetEngine == TargetEngine.Native && taskGdbServer.IsCompleted) { token.ThrowIfCancellationRequested(); throw new LauncherException(Telemetry.LaunchFailureCode.GDBServerFailed, LauncherResources.Error_GDBServerFailed); } if (_launchOptions.LogcatServiceId != Guid.Empty) { _eventCallback.OnCustomDebugEvent(_launchOptions.LogcatServiceId, new Guid(LogcatServiceMessage_SourceId), LogcatServiceMessage_NewProcess, _appProcessId, null); } LaunchOptions launchOptions = null; if (_targetEngine == TargetEngine.Native) { launchOptions = new LocalLaunchOptions(_installPaths.GDBPath, string.Format(CultureInfo.InvariantCulture, ":{0}", gdbPortNumber), 0, null); launchOptions.ExePath = exePath; } else { launchOptions = new JavaLaunchOptions(_launchOptions.JVMHost, _launchOptions.JVMPort, _launchOptions.SourceRoots, _launchOptions.Package); } launchOptions.AdditionalSOLibSearchPath = _launchOptions.AdditionalSOLibSearchPath; launchOptions.AbsolutePrefixSOLibSearchPath = _launchOptions.AbsolutePrefixSOLibSearchPath; // The default ABI is 'Cygwin' in the Android NDK >= r11 for Windows. launchOptions.SetupCommands = new ReadOnlyCollection<LaunchCommand>( new LaunchCommand[] { new LaunchCommand("-gdb-set osabi GNU/Linux") }); launchOptions.TargetArchitecture = _launchOptions.TargetArchitecture; launchOptions.WorkingDirectory = _launchOptions.IntermediateDirectory; launchOptions.DebuggerMIMode = MIMode.Gdb; launchOptions.VisualizerFile = "Microsoft.Android.natvis"; launchOptions.WaitDynamicLibLoad = _launchOptions.WaitDynamicLibLoad; return launchOptions; } }