示例#1
0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public void SetupPortForwarding ()
    {
      // 
      // Setup network redirection.
      // 

      LoggingUtils.PrintFunction ();

      StringBuilder forwardArgsBuilder = new StringBuilder ();

      forwardArgsBuilder.AppendFormat ("tcp:{0} ", Port);

      if (!string.IsNullOrWhiteSpace (Socket))
      {
        forwardArgsBuilder.AppendFormat ("localfilesystem:{0}/{1}", Process.DataDirectory, Socket);
      }
      else
      {
        forwardArgsBuilder.AppendFormat ("tcp:{0} ", Port);
      }

      using (SyncRedirectProcess adbPortForward = AndroidAdb.AdbCommand (Process.HostDevice, "forward", forwardArgsBuilder.ToString ()))
      {
        adbPortForward.StartAndWaitForExit ();
      }
    }
示例#2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public string Push(string localPath, string remotePath)
        {
            LoggingUtils.PrintFunction();

            try
            {
                int exitCode = -1;

                using (SyncRedirectProcess process = AndroidAdb.AdbCommand(this, "push", string.Format("{0} {1}", PathUtils.QuoteIfNeeded(localPath), remotePath)))
                {
                    exitCode = process.StartAndWaitForExit();

                    if (exitCode != 0)
                    {
                        throw new InvalidOperationException(string.Format("[push] returned error code: {0}", exitCode));
                    }

                    return(process.StandardOutput);
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                throw new InvalidOperationException("[push] failed", e);
            }
        }
示例#3
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public string Shell(string command, string arguments, int timeout = 30000)
        {
            LoggingUtils.PrintFunction();

            try
            {
                int exitCode = -1;

                using (SyncRedirectProcess process = AndroidAdb.AdbCommand(this, "shell", string.Format("{0} {1}", command, arguments)))
                {
                    exitCode = process.StartAndWaitForExit(timeout);

                    if (exitCode != 0)
                    {
                        throw new InvalidOperationException(string.Format("[shell:{0}] returned error code: {1}", command, exitCode));
                    }

                    return(process.StandardOutput);
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                throw new InvalidOperationException(string.Format("[shell:{0}] failed", command), e);
            }
        }
示例#4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void ClearPortForwarding()
        {
            //
            // Clear network redirection.
            //

            LoggingUtils.PrintFunction();

            StringBuilder forwardArgsBuilder = new StringBuilder();

            forwardArgsBuilder.AppendFormat("--remove tcp:{0}", Port);

            using SyncRedirectProcess adbPortForward = AndroidAdb.AdbCommand(Process.HostDevice, "forward", forwardArgsBuilder.ToString());

            adbPortForward.StartAndWaitForExit(1000);
        }
示例#5
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void SetupPortForwarding()
        {
            //
            // Setup network redirection.
            //

            LoggingUtils.PrintFunction();

            StringBuilder forwardArgsBuilder = new StringBuilder();

            forwardArgsBuilder.AppendFormat("tcp:{0} jdwp:{1}", Port, Process.Pid);

            using (SyncRedirectProcess adbPortForward = AndroidAdb.AdbCommand(Process.HostDevice, "forward", forwardArgsBuilder.ToString()))
            {
                adbPortForward.StartAndWaitForExit(1000);
            }
        }
示例#6
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void Start()
        {
            LoggingUtils.PrintFunction();

            //
            // Check the target 'gdbserver' binary exits on target device/emulator.
            //

            string gdbServerPath = string.Empty;

            List <string> potentialGdbServerPaths = new List <string> ();

            foreach (string libraryPath in m_gdbSetup.Process.NativeLibraryAbiPaths)
            {
                potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", libraryPath));
            }

            potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", m_gdbSetup.Process.NativeLibraryPath));

            foreach (string path in potentialGdbServerPaths)
            {
                using (SyncRedirectProcess checkGdbServer = AndroidAdb.AdbCommand(m_gdbSetup.Process.HostDevice, "shell", "ls " + path))
                {
                    int exitCode = checkGdbServer.StartAndWaitForExit(1000);

                    if ((exitCode == 0) && !checkGdbServer.StandardOutput.ToLower().Contains("no such file"))
                    {
                        gdbServerPath = path;

                        break;
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(gdbServerPath))
            {
                // TODO: Push the required gdbserver binary, so we can attach to any app.
                throw new InvalidOperationException(string.Format("Failed to locate required 'gdbserver' binary on device ({0}).", m_gdbSetup.Process.HostDevice.ID));
            }

            KillActiveGdbServerSessions();

            //
            // Construct a adaptive command line based on GdbSetup requirements.
            //

            StringBuilder commandLineArgumentsBuilder = new StringBuilder();

            commandLineArgumentsBuilder.AppendFormat("run-as {0} {1} ", m_gdbSetup.Process.Name, gdbServerPath);

            if (!string.IsNullOrWhiteSpace(m_gdbSetup.Socket))
            {
                commandLineArgumentsBuilder.AppendFormat("+{0} ", m_gdbSetup.Socket);
            }

            commandLineArgumentsBuilder.Append("--attach ");

            if (string.IsNullOrWhiteSpace(m_gdbSetup.Socket)) // Don't need a host if we have a bound socket?
            {
                commandLineArgumentsBuilder.AppendFormat("{0}:{1} ", m_gdbSetup.Host, m_gdbSetup.Port);
            }

            commandLineArgumentsBuilder.Append(m_gdbSetup.Process.Pid);

            //
            // Launch 'gdbserver' and wait for output to determine success.
            //

            Stopwatch waitForConnectionTimer = new Stopwatch();

            waitForConnectionTimer.Start();

            m_gdbServerAttached = new ManualResetEvent(false);

            m_gdbServerInstance = AndroidAdb.AdbCommandAsync(m_gdbSetup.Process.HostDevice, "shell", commandLineArgumentsBuilder.ToString());

            m_gdbServerInstance.Start(this);

            LoggingUtils.Print(string.Format("[GdbServer] Waiting to attach..."));

            uint timeout = 5000;

            bool responseSignaled = false;

            while ((!responseSignaled) && (waitForConnectionTimer.ElapsedMilliseconds < timeout))
            {
                responseSignaled = m_gdbServerAttached.WaitOne(0);

                if (!responseSignaled)
                {
                    Thread.Sleep(100);
                }
            }

            if (!responseSignaled)
            {
                throw new TimeoutException("Timed out waiting for GdbServer to execute.");
            }
        }
示例#7
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public string Pull(string remotePath, string localPath)
        {
            LoggingUtils.PrintFunction();

            try
            {
                //
                // Check if the remote path is a symbolic link, and adjust the target file.
                // (ADB Pull doesn't follow these links)
                //

                try
                {
                    string readlink = Shell("readlink", remotePath).Replace("\r", "").Replace("\n", "");

                    if (readlink.StartsWith("/")) // absolute path link
                    {
                        remotePath = readlink;
                    }
                    else // relative path link
                    {
                        int i = remotePath.LastIndexOf('/');

                        if (i != -1)
                        {
                            string parentPath = remotePath.Substring(0, i);

                            string file = remotePath.Substring(i + 1);

                            remotePath = parentPath + '/' + file;
                        }
                    }
                }
                catch (Exception)
                {
                    // Ignore. Not a relative link.
                }

                //
                // Pull the requested file.
                //

                int exitCode = -1;

                using (SyncRedirectProcess process = AndroidAdb.AdbCommand(this, "pull", string.Format("{0} {1}", remotePath, PathUtils.QuoteIfNeeded(localPath))))
                {
                    exitCode = process.StartAndWaitForExit();

                    if (exitCode != 0)
                    {
                        throw new InvalidOperationException(string.Format("[pull] returned error code: {0}", exitCode));
                    }

                    return(process.StandardOutput);
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                throw new InvalidOperationException("[pull] failed", e);
            }
        }
示例#8
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void Start()
        {
            LoggingUtils.PrintFunction();

            //
            // Check the target 'gdbserver' binary exits on target device/emulator.
            //

            string gdbServerPath = string.Empty;

            List <string> potentialGdbServerPaths = new List <string> ();

            foreach (string libraryPath in m_gdbSetup.Process.NativeLibraryAbiPaths)
            {
                potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", libraryPath));
            }

            potentialGdbServerPaths.Add(string.Format("{0}/gdbserver", m_gdbSetup.Process.NativeLibraryPath));

            foreach (string path in potentialGdbServerPaths)
            {
                try
                {
                    string ls = m_gdbSetup.Process.HostDevice.Shell("ls", path);

                    if (ls.ToLowerInvariant().Contains("no such file"))
                    {
                        throw new DirectoryNotFoundException(path);
                    }

                    gdbServerPath = path;

                    break;
                }
                catch (Exception)
                {
                    // Ignore.
                }
            }

            //
            // If we can't find a bundled 'gdbserver' binary, attempt to find one in the NDK.
            //

            if (string.IsNullOrWhiteSpace(gdbServerPath))
            {
                foreach (string path in m_gdbSetup.Process.NativeLibraryAbiPaths)
                {
                    try
                    {
                        string shortAbi = path.Substring(path.LastIndexOf('/') + 1);

                        string local = Path.Combine(AndroidSettings.NdkRoot, string.Format(@"prebuilt\android-{0}\gdbserver\gdbserver", shortAbi));

                        string remote = string.Format("/data/local/tmp/gdbserver-{0}", shortAbi);

                        m_gdbSetup.Process.HostDevice.Push(local, remote);
                    }
                    catch (Exception e)
                    {
                        LoggingUtils.HandleException(e);
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(gdbServerPath))
            {
                throw new InvalidOperationException(string.Format("Failed to locate required 'gdbserver' binary on device ({0}).", m_gdbSetup.Process.HostDevice.ID));
            }

            KillActiveGdbServerSessions();

            //
            // Construct a adaptive command line based on GdbSetup requirements.
            //

            StringBuilder commandLineArgumentsBuilder = new StringBuilder();

            commandLineArgumentsBuilder.AppendFormat("run-as {0} {1} ", m_gdbSetup.Process.Name, gdbServerPath);

            if (!string.IsNullOrWhiteSpace(m_gdbSetup.Socket))
            {
                commandLineArgumentsBuilder.AppendFormat("+{0} ", m_gdbSetup.Socket);
            }

            commandLineArgumentsBuilder.Append("--attach ");

            if (string.IsNullOrWhiteSpace(m_gdbSetup.Socket)) // Don't need a host if we have a bound socket?
            {
                commandLineArgumentsBuilder.AppendFormat("{0}:{1} ", m_gdbSetup.Host, m_gdbSetup.Port);
            }

            commandLineArgumentsBuilder.Append(m_gdbSetup.Process.Pid);

            //
            // Launch 'gdbserver' and wait for output to determine success.
            //

            Stopwatch waitForConnectionTimer = new Stopwatch();

            waitForConnectionTimer.Start();

            m_gdbServerAttached = new ManualResetEvent(false);

            m_gdbServerInstance = AndroidAdb.AdbCommandAsync(m_gdbSetup.Process.HostDevice, "shell", commandLineArgumentsBuilder.ToString());

            m_gdbServerInstance.Start(this);

            LoggingUtils.Print(string.Format("[GdbServer] Waiting to attach..."));

            uint timeout = 5000;

            bool responseSignaled = false;

            while ((!responseSignaled) && (waitForConnectionTimer.ElapsedMilliseconds < timeout))
            {
                responseSignaled = m_gdbServerAttached.WaitOne(0);

                if (!responseSignaled)
                {
                    Thread.Sleep(100);
                }
            }

            if (!responseSignaled)
            {
                throw new TimeoutException("Timed out waiting for GdbServer to execute.");
            }
        }