コード例 #1
0
        /// <summary>
        /// Runs the process and read output.
        /// </summary>
        /// <returns>The process and read output.</returns>
        /// <param name="processName">Process name.</param>
        /// <param name="processArgs">Process arguments.</param>
        /// <param name="timeout">Timeout.</param>
        public string RunProcessAndReadOutput(string processName, string processArgs, int timeout = 5000)
        {
            _logger.Debug(string.Format("RunProcessAndReadOutput processName: [{0}] args: [{1}]", processName,
                                        processArgs));

            var psi = new ProcessStartInfo()
            {
                FileName               = processName,
                Arguments              = processArgs,
                UseShellExecute        = false,
                RedirectStandardOutput = true,
                RedirectStandardError  = true
            };
            var proc = new Process
            {
                StartInfo = psi
            };

            proc.Start();

            proc.WaitForExit(timeout);

            var output = proc.StandardOutput.ReadToEnd();

            _logger.Debug(string.Format("RunProcessAndReadOutput output: [{0}]", string.Join("\n", output)));

            var errorOutput = proc.StandardError.ReadToEnd();

            _logger.Debug(string.Format("RunProcessAndReadOutput errorOutput: [{0}]",
                                        string.Join("\n", errorOutput)));

            return(output + errorOutput);
        }
コード例 #2
0
        public IActionResult Create([FromBody] AppiumProcess appiumProcess)
        {
            LogRequestToDebug();

            if (!ValidateAppiumProcess(appiumProcess, out var badRequest))
            {
                return(badRequest);
            }

            if (_appiumRepository.Find(appiumProcess.DeviceId) != null)
            {
                // 409 = Conflict
                return(StatusCodeExtension(409,
                                           $"Appium is already running for {nameof(AppiumProcess.DeviceId)} [{appiumProcess.DeviceId}]."));
            }

            try
            {
                _appiumRepository.Add(appiumProcess);
            }
            catch (Exception ex)
            {
                return(StatusCodeExtension(500, "Failed to Add AppiumProcess in database. " + ex.Message));
            }

            _logger.Debug(string.Format("Created new appiumProcess: [{0}]",
                                        JsonConvert.SerializeObject(appiumProcess)));

            return(CreatedAtRoute("getAppiumProcess", new { id = appiumProcess.DeviceId }, appiumProcess));
        }
コード例 #3
0
        /// <inheritdoc />
        /// <summary>
        /// Takes the screenshot ios device.
        /// </summary>
        /// <returns>The screenshot ios device.</returns>
        /// <param name="device">Device.</param>
        public FileStreamResult TakeScreenshotIosDevice(Device device)
        {
            var screenshotFolder = Path.Combine(Directory.GetCurrentDirectory(), "Screenshot");

            Directory.CreateDirectory(screenshotFolder);
            var screenshotFilePath = Path.Combine(screenshotFolder, $"{device.Id}.tiff");

            var screenshotRet = _externalProcesses.RunProcessAndReadOutput("idevicescreenshot",
                                                                           $" -u {device.Id} {screenshotFilePath}", 10000);

            _logger.Debug(screenshotRet);

            if (screenshotRet.Contains("Could not start screenshotr service"))
            {
                //throw new Exception($"Failed get screenshot. {screenshotRet}");
                return(GetDefaultMobileImage());
            }

            var convertedImagePath = Path.Combine(screenshotFolder, $"{device.Id}.jpg");

            ConvertImage(screenshotFilePath, convertedImagePath);

            FileStream image;

            if (System.IO.File.Exists(convertedImagePath))
            {
                image = System.IO.File.OpenRead(convertedImagePath);
                return(File(image, "image/jpeg"));
            }

            image = System.IO.File.OpenRead(screenshotFilePath);
            return(File(image, "image/tiff"));
        }
コード例 #4
0
        public IEnumerable <Device> GetAll()
        {
            LogRequestToDebug();

            var devices = _devicesRepository.GetAll();

            _logger.Debug(string.Format("GetAll devices: [{0}]", JsonConvert.SerializeObject(devices)));
            return(devices);
        }
コード例 #5
0
        public IEnumerable <ReservationApplied> GetAllAppliedReservations()
        {
            LogRequestToDebug();

            var reservations = _reservationsAppliedRepository.GetAll();

            _logger.Debug(
                string.Format("GetAll reservations applied: [{0}]", JsonConvert.SerializeObject(reservations)));
            return(reservations);
        }
コード例 #6
0
        public async Task <IActionResult> Delete(string id)
        {
            LogRequestToDebug();

            var device = await _restClient.GetDevice(id);

            if (device == null)
            {
                return(NotFoundExtension("DeviceId not found in database."));
            }

            String appiumLogPath = await GetAppiumLogFilePath(id);

            if (!System.IO.File.Exists(appiumLogPath))
            {
                return(NotFoundExtension("Appium log not found on path:" + appiumLogPath));
            }

            try
            {
                System.IO.File.Delete(appiumLogPath);
            }
            catch (Exception ex)
            {
                return(StatusCodeExtension(500, "Failed to delete AppiumLog. " + ex.Message));
            }

            _logger.Debug(string.Format("Successfully deleted appiumLog on path: [{0}]", appiumLogPath));

            return(OkExtension());
        }
コード例 #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:MobileManager.Services.AndroidDeviceService"/> class.
 /// </summary>
 public AndroidDeviceService(IManagerConfiguration configuration, IManagerLogger logger, IExternalProcesses externalProcesses)
 {
     _logger            = logger;
     _externalProcesses = externalProcesses;
     _logger.Debug("Running AndroidDeviceService service.");
     _deviceUtils = new DeviceUtils(_logger, _externalProcesses);
     _restClient  = new RestClient(configuration, _logger);
 }
コード例 #8
0
        public IActionResult Command([FromBody] AdbCommand adbCommand)
        {
            if (!IsAdbCommandExecutable(adbCommand, out var actionResult))
            {
                return(actionResult);
            }

            string output;

            try
            {
                output = _externalProcesses.RunProcessAndReadOutput("adb",
                                                                    $"-s {adbCommand.AndroidDeviceId} {adbCommand.Command}");
                _logger.Debug($"{nameof(AdbCommand)} [{adbCommand.Command}] output: [{output}]");
            }
            catch (Exception ex)
            {
                return(StatusCodeExtension(500, "Failed to run adb command. " + ex.Message));
            }

            return(StatusCodeExtension(200, output));
        }
コード例 #9
0
 public BadRequestObjectResult BadRequestExtension(object error)
 {
     _logger.Debug(string.Format("Response status code: [{0}], message: [{1}]", 400,
                                 JsonConvert.SerializeObject(error)));
     return(BadRequest(error));
 }
コード例 #10
0
        /// <inheritdoc />
        /// <summary>
        /// Locks the device.
        /// </summary>
        /// <returns>The device.</returns>
        /// <param name="deviceId">Device identifier.</param>
        /// <param name="restClient">Rest client.</param>
        /// <param name="appiumService">Appium service.</param>
        public async Task <Device> LockDevice(string deviceId, IRestClient restClient,
                                              IAppiumService appiumService)
        {
            _logger.Debug($"{nameof(LockDevice)}: device id [{deviceId}].");

            var device = await restClient.GetDevice(deviceId);

            if (device == null)
            {
                throw new KeyNotFoundException("Failed to find device with id: " + deviceId);
            }

            _logger.Debug(
                $"{nameof(LockDevice)}: set device id [{deviceId}] available from [{device.Available}] to false.");
            device.Available = false;

            _logger.Debug($"{nameof(LockDevice)}: device id [{deviceId}] stop running Appium");
            try
            {
                device.AppiumEndpoint = Task.Run(() => appiumService.StartAppiumForDeviceId(deviceId)).Result;
            }
            catch (Exception e)
            {
                _logger.Error($"{nameof(LockDevice)} failed with exception.", e);
                await UnlockDevice(device.Id, restClient, appiumService);

                throw;
            }

            _logger.Debug($"{nameof(LockDevice)}: device id [{deviceId}] set status from [{device.Status}] to LOCKED");

            device.Status = DeviceStatus.Locked;

            var updatedDevice = await restClient.UpdateDevice(device);

            _logger.Debug($"{nameof(LockDevice)}: updated device [{JsonConvert.SerializeObject(updatedDevice)}]");

            return(updatedDevice);
        }
コード例 #11
0
        /// <summary>
        /// Loads the connected IOS Devices async.
        /// </summary>
        /// <returns>The connected IOS Devices async.</returns>
        private async Task LoadConnectedIosDevicesAsync(CancellationToken cancellationToken)
        {
            _logger.Info($"{nameof(LoadConnectedIosDevicesAsync)} Thread started.");
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    _logger.Debug($"Running {nameof(LoadConnectedIosDevicesAsync)}.");

                    if (await _restClient.TryToConnect())
                    {
                        var output             = _externalProcesses.RunProcessAndReadOutput("idevice_id", "-l");
                        var listOfIosDeviceIds =
                            output.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList();
                        listOfIosDeviceIds = listOfIosDeviceIds.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct()
                                             .ToList();

                        await _deviceUtils.CheckAllDevicesInDevicePoolAreOnline(listOfIosDeviceIds, DeviceType.IOS,
                                                                                _restClient);

                        foreach (var deviceId in listOfIosDeviceIds)
                        {
                            if (string.IsNullOrEmpty(deviceId))
                            {
                                continue;
                            }

                            var deviceInDevicePool = await _restClient.GetDevice(deviceId);

                            if (deviceInDevicePool != null)
                            {
                                if (deviceInDevicePool.Status == DeviceStatus.Offline)
                                {
                                    SetNewDeviceProperties(deviceInDevicePool);
                                    await MountDeveloperDiskAsync(deviceInDevicePool);

                                    deviceInDevicePool.Status    = DeviceStatus.Online;
                                    deviceInDevicePool.Available = true;
                                    await _restClient.UpdateDevice(deviceInDevicePool);

                                    continue;
                                }

                                _logger.Info(
                                    $"{nameof(LoadConnectedIosDevicesAsync)}: Device {deviceId} is already stored in database.");
                                await MountDeveloperDiskAsync(deviceInDevicePool);

                                continue;
                            }

                            var deviceName =
                                _externalProcesses.RunProcessAndReadOutput("idevicename", $"-u {deviceId}");

                            if (string.IsNullOrEmpty(deviceName) || deviceName.Contains("ERROR"))
                            {
                                _logger.Error(
                                    $"{nameof(LoadConnectedIosDevicesAsync)}: Failed get device name for deviceId: [{deviceId}].\n[{deviceName}]");
                                continue;
                            }

                            var device = new DeviceFactory().NewDevice(deviceId, deviceName.Trim('\n'), true,
                                                                       DeviceType.IOS, DeviceStatus.Online);
                            SetNewDeviceProperties(device);

                            await TryAddNewDeviceToDevicePoolAsync(device);

                            await MountDeveloperDiskAsync(device);
                        }

                        Thread.Sleep((await _restClient.GetManagerConfiguration()).IosDeviceServiceRefreshTime);
                    }
                    else
                    {
                        _logger.Error(
                            $"{nameof(LoadConnectedIosDevicesAsync)}: Failed connecting to {_restClient.Endpoint} [STOP]");
                        WaitForGlobalReconnectTimeout();
                    }
                }
                catch (Exception e)
                {
                    _logger.Error($"{nameof(LoadConnectedIosDevicesAsync)} exception.", e);
                    WaitForGlobalReconnectTimeout();
                }
            }
        }
コード例 #12
0
        /// <inheritdoc />
        /// <summary>
        /// Starts the appium for device identifier.
        /// </summary>
        /// <returns>The appium for device identifier.</returns>
        /// <param name="deviceId">Device identifier.</param>
        public async Task <string> StartAppiumForDeviceId(string deviceId)
        {
            _logger.Info($"{nameof(StartAppiumForDeviceId)} {deviceId} Thread Started.");
            var configuration = await _restClient.GetManagerConfiguration();

            var device = await _restClient.GetDevice(deviceId);

            _logger.Debug($"{nameof(StartAppiumForDeviceId)} - device: {JsonConvert.SerializeObject(device)}");

            var appiumIpAddress        = configuration.LocalIpAddress;
            var currentAppiumProcesses = await _restClient.GetAppiumProcesses();

            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - currentAppiumProcesses: {JsonConvert.SerializeObject(currentAppiumProcesses)}");

            var usedAppiumPorts = new List <string>();

            foreach (var process in currentAppiumProcesses)
            {
                usedAppiumPorts.Add(process.AppiumPort);
                usedAppiumPorts.Add(process.AppiumBootstrapPort);
                usedAppiumPorts.Add(process.WebkitDebugProxyPort);
                usedAppiumPorts.Add(process.WdaLocalPort);
            }

            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - usedAppiumPorts: {JsonConvert.SerializeObject(usedAppiumPorts)}");

            var appiumPort = GetFreePortAsyncMac(configuration, usedAppiumPorts);

            usedAppiumPorts.Add(appiumPort);
            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - new appiumPort: {JsonConvert.SerializeObject(appiumPort)}");

            var appiumBootstrapPort = GetFreePortAsyncMac(configuration, usedAppiumPorts);

            usedAppiumPorts.Add(appiumBootstrapPort);
            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - new appiumBootstrapPort: {JsonConvert.SerializeObject(appiumBootstrapPort)}");

            var appiumLogFilePath = _appiumLogFolderPath;

            if (!appiumLogFilePath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            {
                appiumLogFilePath += Path.DirectorySeparatorChar;
            }

            appiumLogFilePath = appiumLogFilePath + deviceId + ".log";
            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - appiumLogFilePath: {JsonConvert.SerializeObject(appiumLogFilePath)}");

            var webkitDebugProxyPort = GetFreePortAsyncMac(configuration, usedAppiumPorts);

            usedAppiumPorts.Add(webkitDebugProxyPort);

            var wdaLocalPort = GetFreePortAsyncMac(configuration, usedAppiumPorts);

            usedAppiumPorts.Add(wdaLocalPort);

            /*
             * String defaultCapabilities = "\\\"automation-name\\\" : \\\"XCUITest\\\"," +
             *  " \\\"teamId\\\" : \\\"CB52FCDD4H\\\"," +
             *  " \\\"signingId\\\" : \\\"iPhone Developer\\\"," +
             *  " \\\"showXcodeLog\\\" : \\\"true\\\"," +
             *  " \\\"realDeviceLogger\\\" : \\\"/usr/local/lib/node_modules/deviceconsole/deviceconsole\\\"," +
             *  " \\\"bootstrapPath\\\" : \\\"/usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent\\\"," +
             *  " \\\"agentPath\\\" : \\\"/usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj\\\"," +
             *  " \\\"startIWDP\\\" : \\\"true\\\"," +
             *  " \\\"sessionTimeout\\\" : \\\"6000\\\"";
             */
            var appiumArguments = "" +
                                  " --session-override" +
                                  " --suppress-adb-kill-server" +
                                  " --log " + appiumLogFilePath +
                                  " --udid " + deviceId +
                                  " --address " + appiumIpAddress +
                                  " --port " + appiumPort +
                                  " --bootstrap-port " + appiumBootstrapPort +
                                  " --webkit-debug-proxy-port " + webkitDebugProxyPort +
                                  " --webdriveragent-port " + wdaLocalPort;

            /*
             * if (device.Type == Devices.Enums.DeviceType.iOS)
             * {
             *  appiumArguments += " --default-capabilities \\\'{"+defaultCapabilities+"}\\\'";
             * }
             */

            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - starting appium with args: {JsonConvert.SerializeObject(appiumArguments)}");

            var appiumPid = _externalProcesses.RunProcessInBackground("appium", appiumArguments);

            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - appium started in terminal with pid: {JsonConvert.SerializeObject(appiumPid)}");

            Thread.Sleep(3000);
            var psOutput = _externalProcesses.RunProcessAndReadOutput("ps", "ax");

            var runningAppiumProcess = psOutput.Split('\n').Where(x => x.Contains("bin/appium") && x.Contains(deviceId))
                                       .ToList();

            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - runningAppiumProcess {JsonConvert.SerializeObject(runningAppiumProcess)} for device {device}.");

            var processId = "";

            if (runningAppiumProcess.Count() != 1)
            {
                _logger.Error(
                    $"{nameof(StartAppiumForDeviceId)}: Multiple appium processes running with deviceId={deviceId}. Killing them all...");
                _externalProcesses.StopProcessRunningInBackground(deviceId);
            }
            else
            {
                processId = runningAppiumProcess.First().Trim().Split()[0];
                _logger.Debug(
                    $"{nameof(StartAppiumForDeviceId)} - runningAppiumProcess with pid: {JsonConvert.SerializeObject(processId)}.");
            }

            if (string.IsNullOrEmpty(processId) &&
                !_externalProcesses.IsProcessInBackgroundRunning(Convert.ToInt32(processId)))
            {
                throw new Exception($"{nameof(StartAppiumForDeviceId)}: Appium process failed to start successfully.");
            }

            appiumPid = Convert.ToInt32(processId);

            var appiumProcess = new AppiumProcess(deviceId, appiumPort, appiumBootstrapPort, appiumPid,
                                                  webkitDebugProxyPort, wdaLocalPort);

            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - adding appiumProcess: {JsonConvert.SerializeObject(appiumProcess)}.");

            var result = Task.Run(async() => await _restClient.AddAppiumProcess(appiumProcess)).Result;

            _logger.Debug(
                $"{nameof(StartAppiumForDeviceId)} - finished adding appiumProcess: with result [{result}].");

            if (device.Type == DeviceType.IOS)
            {
                _logger.Debug($"{nameof(StartAppiumForDeviceId)} - starting iosWebkit for ios device {device}.");

                var iosWebkitPid = StartIosWebkitDebugProxy(deviceId, webkitDebugProxyPort);
                if (!_externalProcesses.IsProcessInBackgroundRunning(iosWebkitPid))
                {
                    _logger.Error(
                        $"{nameof(StartAppiumForDeviceId)} - ios_webkit_debug_proxy process failed to start successfully.");

                    throw new Exception(
                              $"{nameof(StartAppiumForDeviceId)}: ios_webkit_debug_proxy process failed to start successfully.");
                }

                _logger.Debug($"{nameof(StartAppiumForDeviceId)} - starting IdeviceSyslog for ios device {device}.");

                StartIdeviceSyslog(deviceId);
            }

            _logger.Info($"{nameof(StartAppiumForDeviceId)} appiumEndpoint: {appiumIpAddress}:{appiumPort}");
            var appiumEndpoint = new Uri($"http://{appiumIpAddress}:{appiumPort}/wd/hub");

            return(appiumEndpoint.ToString());
        }
コード例 #13
0
        /// <inheritdoc />
        /// <summary>
        /// Applies the available reservations.
        /// </summary>
        /// <returns>The available reservations.</returns>
        //todo refactor - split into multiple methods
        public async Task <bool> ApplyAvailableReservations()
        {
            var reservationQueue = await LoadReservationQueue();

            var appliedReservations = new List <ReservationApplied>();

            foreach (var reservation in reservationQueue)
            {
                _logger.Info($"Applying reservation - item in queue: {JsonConvert.SerializeObject(reservation)}");
                var reservedDevices = new List <ReservedDevice>();

                if (reservation.RequestedDevices == null)
                {
                    throw new NullReferenceException("RequestedDevices property on reservation is empty.");
                }

                var reservationEligible = true;
                if (reservation.RequestedDevices.Count > 1)
                {
                    reservationEligible = await IsReservationEligible(reservation);
                }

                if (reservationEligible)
                {
                    await ReserveAllRequestedDevices(reservation, reservedDevices);
                }
                else
                {
                    _logger.Debug($"Reservation is not eligible. {JsonConvert.SerializeObject(reservation)}");
                    continue;
                }

                if (reservedDevices.Count == reservation.RequestedDevices.Count)
                {
                    //ICollection<ReservationApplied> reservationApplied = null;
                    try
                    {
                        var reservationApplied = await AddAppliedReservation(appliedReservations, reservation,
                                                                             reservedDevices);

                        appliedReservations.AddRange(reservationApplied);
                    }
                    catch (Exception e)
                    {
                        _logger.Error($"Failed to AddAppliedReservation.", e);
                        await UnlockAllReservedDevices(reservedDevices);

                        continue;
                    }

                    _logger.Info(
                        $"Applying reservation - removing reservation from queue: {JsonConvert.SerializeObject(reservation)}");
                    await RestClient.DeleteReservation(reservation.Id);
                }
                else if (reservedDevices.Any())
                {
                    await UnlockAllReservedDevices(reservedDevices);
                }
            }

            _logger.Info(
                $"Applying reservation - applied reservations: {JsonConvert.SerializeObject(appliedReservations)}");
            return(appliedReservations.Any());
        }
コード例 #14
0
        /// <inheritdoc />
        /// <summary>
        /// Tries to connect.
        /// </summary>
        /// <returns>The to connect.</returns>
        public async Task <bool> TryToConnect()
        {
            _logger.Debug("Starting TryToConnect");
            try
            {
                await _client.GetAsync("api/v1/configuration");
            }
            catch (Exception e)
            {
                _logger.Info("Failed to connect to: " + _client.BaseAddress);
                _logger.Error("Failed to connect.", e);
                return(false);
            }

            _logger.Debug("Finished TryToConnect OK");
            return(true);
        }
コード例 #15
0
        private async Task LoadConnectedAndroidDevicesAsync(CancellationToken cancellationToken)
        {
            _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)} Thread started.");
            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    _logger.Debug($"Running {nameof(LoadConnectedAndroidDevicesAsync)}.");

                    if (await _restClient.TryToConnect())
                    {
                        var deviceIdAndStatus = GetAndroidDevicesFromAdbDevicesOutput();

                        await _deviceUtils.CheckAllDevicesInDevicePoolAreOnline(deviceIdAndStatus.Keys.ToList(),
                                                                                DeviceType.Android, _restClient);

                        foreach (var deviceId in deviceIdAndStatus.Keys)
                        {
                            var deviceAlreadyInPool = await IsDeviceAlreadyInDevicePoolAsync(deviceId);

                            if (!deviceAlreadyInPool)
                            {
                                var state = deviceIdAndStatus[deviceId];
                                if (state != "device")
                                {
                                    _logger.Error(
                                        $"{nameof(LoadConnectedAndroidDevicesAsync)}: Device with id: [{deviceId}] is in incorrect state: [{state}]. Expected state is [device]");
                                    continue;
                                }
                            }
                            else
                            {
                                continue;
                            }

                            _logger.Debug(
                                $"{nameof(LoadConnectedAndroidDevicesAsync)}: read device [{deviceId}] properties.");
                            var deviceName = GetDeviceName(deviceId);

                            if (string.IsNullOrWhiteSpace(deviceName))
                            {
                                _logger.Error(
                                    $"{nameof(LoadConnectedAndroidDevicesAsync)}: Failed to get deviceName to device with id: '" +
                                    deviceId + "'");
                                continue;
                            }

                            _logger.Debug(
                                $"{nameof(LoadConnectedAndroidDevicesAsync)}: new android device factory [{deviceId}] name [{deviceName.Trim('\n', '\r')}].");
                            var device = new DeviceFactory().NewDevice(deviceId, deviceName.Trim('\n', '\r'), true,
                                                                       DeviceType.Android, DeviceStatus.Online);

                            var deviceProperties = GetDevicePropertiesById(deviceId);

                            var properties = new List <DeviceProperties>();
                            foreach (var prop in deviceProperties)
                            {
                                properties.Add(new DeviceProperties(prop.Key, prop.Value));
                            }

                            device.Properties = properties;

                            await TryAddNewDeviceToDevicePoolAsync(device);

                            _logger.Debug(
                                $"{nameof(LoadConnectedAndroidDevicesAsync)}: TryAddNewDeviceToDevicePoolAsync [{JsonConvert.SerializeObject(device)}].");
                            await TryAddNewDeviceToDevicePoolAsync(device);
                        }

                        var sleepTime = (await _restClient.GetManagerConfiguration()).AndroidDeviceServiceRefreshTime;
                        _logger.Debug($"{nameof(LoadConnectedAndroidDevicesAsync)}: sleep for [{sleepTime}].");
                        Thread.Sleep(sleepTime);
                    }
                    else
                    {
                        _logger.Error($"{nameof(LoadConnectedAndroidDevicesAsync)}: Failed connecting to " +
                                      _restClient.Endpoint +
                                      " [STOP]");
                        var sleep = AppConfigurationProvider.Get <ManagerConfiguration>().GlobalReconnectTimeout;
                        _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)}: Sleep for [ms]: {sleep}");
                        Thread.Sleep(sleep);
                        _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)}: Sleep finished");
                    }
                }

                _logger.Info($"{nameof(LoadConnectedAndroidDevicesAsync)} STOP.");
            }
            catch (Exception e)
            {
                _logger.Error($"Stopping {nameof(LoadConnectedAndroidDevicesAsync)}.", e);
            }

            if (cancellationToken.IsCancellationRequested)
            {
                var result = _externalProcesses.RunProcessAndReadOutput("adb", "kill-server");
                _logger.Debug(
                    $"{nameof(LoadConnectedAndroidDevicesAsync)}: Stop ADB server to release ports - output:{result}");
            }
        }