void EndLaunch()
        {
            if (alreadyEnded)
            {
                return;
            }
            alreadyEnded = true;

            if (launchOp != null && !launchOp.IsCompleted)
            {
                try {
                    launchOp.Cancel();
                    launchOp = null;
                } catch {}
            }

            if (trackProcessOp != null && !trackProcessOp.IsCompleted)
            {
                // This operation should finish by itself, but make sure it's actually done.
                try {
                    trackProcessOp.Cancel();
                    trackProcessOp = null;
                } catch {}
            }

            if (debugPropertySet)
            {
                try {
                    MonoDroidFramework.Toolbox.SetProperty(debugDevice, "debug.mono.extra", String.Empty);
                } catch {}
            }
        }
		public IProcessAsyncOperation Execute (ExecutionCommand command, IConsole console)
		{
			var cmd = (MonoDroidExecutionCommand) command;
			int runningProcessId = -1;

			var launchOp = new ChainedAsyncOperationSequence (
				new ChainedAsyncOperation<AdbGetProcessIdOperation> () {
					Create = () => new AdbGetProcessIdOperation (cmd.Device, cmd.PackageName),
					Completed = (op) => {
						if (op.Success)
							runningProcessId = op.ProcessId;
					}
				},
				new ChainedAsyncOperation () {
					Skip = () => runningProcessId <= 0 ? "" : null,
					Create = () => new AdbShellOperation (cmd.Device, "kill " + runningProcessId)
				},
				new ChainedAsyncOperation () {
					Create = () => MonoDroidFramework.Toolbox.StartActivity (cmd.Device, cmd.Activity)
				}
			);
			launchOp.Start ();

			return new MonoDroidProcess (cmd.Device, cmd.Activity, cmd.PackageName, 
				console.Out.Write, console.Error.Write, launchOp);
		}
        protected override void OnRun(DebuggerStartInfo startInfo)
        {
            var dsi       = (MonoDroidDebuggerStartInfo)startInfo;
            var cmd       = dsi.ExecutionCommand;
            var startArgs = (SoftDebuggerRemoteArgs)dsi.StartArgs;

            debugDevice = cmd.Device;

            bool alreadyForwarded = MonoDroidFramework.DeviceManager.GetDeviceIsForwarded(cmd.Device.ID);

            if (!alreadyForwarded)
            {
                MonoDroidFramework.DeviceManager.SetDeviceLastForwarded(null);
            }

            long     date             = 0;
            int      runningProcessId = 0;        // Already running activity
            DateTime setPropertyTime  = DateTime.MinValue;

            launchOp = new ChainedAsyncOperationSequence(
                new ChainedAsyncOperation <AdbGetDateOperation> ()
            {
                Create    = () => MonoDroidFramework.Toolbox.GetDeviceDate(cmd.Device),
                Completed = (op) => {
                    if (op.Success)
                    {
                        date            = op.Date;
                        setPropertyTime = DateTime.Now;
                    }
                    else
                    {
                        this.OnDebuggerOutput(true, GettextCatalog.GetString("Failed to get date from device"));
                        this.OnDebuggerOutput(true, op.Output);
                    }
                },
            },
                new ChainedAsyncOperation <AdbShellOperation> ()
            {
                Create = () => {
                    this.OnDebuggerOutput(false, GettextCatalog.GetString("Setting debug property") + "\n");
                    long expireDate    = date + (DEBUGGER_TIMEOUT_MS / 1000);
                    string monoOptions = string.Format("debug={0}:{1}:{2},timeout={3},server=y", startArgs.Address, startArgs.DebugPort, startArgs.OutputPort, expireDate);
                    return(MonoDroidFramework.Toolbox.SetProperty(cmd.Device, "debug.mono.extra", monoOptions));
                },
                Completed = (op) => {
                    if (!op.Success)
                    {
                        this.OnDebuggerOutput(true, GettextCatalog.GetString("Failed to set debug property on device"));
                        this.OnDebuggerOutput(true, op.Output);
                    }
                    else
                    {
                        debugPropertySet = true;
                    }
                }
            },
                new ChainedAsyncOperation()
            {
                Skip   = () => alreadyForwarded? "" : null,
                Create = () => {
                    this.OnDebuggerOutput(false, GettextCatalog.GetString("Forwarding debugger port") + "\n");
                    return(MonoDroidFramework.Toolbox.ForwardPort(cmd.Device, startArgs.DebugPort, startArgs.DebugPort, DebuggerOutput, DebuggerError));
                },
                Completed = (op) => {
                    if (!op.Success)
                    {
                        this.OnDebuggerOutput(true, GettextCatalog.GetString("Failed to forward port on device"));
                    }
                }
            },
                new ChainedAsyncOperation()
            {
                Skip   = () => alreadyForwarded? "" : null,
                Create = () => {
                    this.OnDebuggerOutput(false, GettextCatalog.GetString("Forwarding console port") + "\n");
                    return(MonoDroidFramework.Toolbox.ForwardPort(cmd.Device, startArgs.OutputPort, startArgs.OutputPort, DebuggerOutput, DebuggerError));
                },
                Completed = (op) => {
                    if (!op.Success)
                    {
                        this.OnDebuggerOutput(true, GettextCatalog.GetString("Failed to forward port on device"));
                    }
                    else
                    {
                        MonoDroidFramework.DeviceManager.SetDeviceLastForwarded(cmd.Device.ID);
                    }
                }
            },
                new ChainedAsyncOperation <AdbGetProcessIdOperation> ()
            {
                Create    = () => new AdbGetProcessIdOperation(cmd.Device, cmd.PackageName),
                Completed = (op) => {
                    if (!op.Success)
                    {
                        this.OnDebuggerOutput(true, "Error trying to detect already running process");
                    }
                    else if (op.ProcessId > 0)
                    {
                        this.OnDebuggerOutput(false, GettextCatalog.GetString("Already running activity detected, restarting it in debug mode") + "\n");
                        runningProcessId = op.ProcessId;
                    }
                }
            },
                new ChainedAsyncOperation()                    // Broadcast a message to kill any previous running instance
            {
                Skip      = () => runningProcessId <= 0 ? "" : null,
                Create    = () => new AdbKillProcessOperation(cmd.Device, cmd.PackageName),
                Completed = (op) => {
                    if (!op.Success)
                    {
                        this.OnDebuggerOutput(true, GettextCatalog.GetString("Failed to stop already running activity"));
                    }
                }
            },
                new ChainedAsyncOperation <AdbShellOperation> ()
            {
                Create    = () => MonoDroidFramework.Toolbox.StartActivity(cmd.Device, cmd.Activity),
                Completed = (op) => {
                    if (!op.Success)
                    {
                        this.OnDebuggerOutput(true, GettextCatalog.GetString("Failed to start activity"));
                    }
                    OnDebuggerOutput(false, op.Output);
                }
            }
                );
            launchOp.Completed += delegate(IAsyncOperation op) {
                if (!op.Success)
                {
                    EndSession();
                    return;
                }
                launchOp = null;

                Action <string> stdout = s => OnTargetOutput(false, s);
                Action <string> stderr = s => OnTargetOutput(true, s);

                trackProcessOp            = new MonoDroidProcess(cmd.Device, cmd.Activity, cmd.PackageName, stdout, stderr);
                trackProcessOp.Completed += delegate {
                    EndSession();
                };

                System.Threading.Thread.Sleep(WAIT_BEFORE_CONNECT_MS);

                var  msSinceSetProperty    = (long)Math.Floor((DateTime.Now - setPropertyTime).TotalMilliseconds);
                long msTillPropertyExpires = DEBUGGER_TIMEOUT_MS - msSinceSetProperty;

                if (msTillPropertyExpires < 100 || msTillPropertyExpires > DEBUGGER_TIMEOUT_MS)
                {
                    return;
                }

                int retries = (int)Math.Floor((double)msTillPropertyExpires / WAIT_BEFORE_RETRY_MS) - 2;

                StartConnecting(dsi, retries, WAIT_BEFORE_RETRY_MS);
            };

            TargetExited += delegate {
                EndLaunch();
            };

            launchOp.Start();
        }
		protected override void OnRun (DebuggerStartInfo startInfo)
		{
			var dsi = (MonoDroidDebuggerStartInfo) startInfo;
			var cmd = dsi.ExecutionCommand;
			debugDevice = cmd.Device;
			
			bool alreadyForwarded = MonoDroidFramework.DeviceManager.GetDeviceIsForwarded (cmd.Device.ID);
			if (!alreadyForwarded)
				MonoDroidFramework.DeviceManager.SetDeviceLastForwarded (null);
			
			long date = 0;
			int runningProcessId = 0; // Already running activity
			DateTime setPropertyTime = DateTime.MinValue;
			launchOp = new ChainedAsyncOperationSequence (
				new ChainedAsyncOperation<AndroidToolbox.GetDateOperation> () {
					Create = () => MonoDroidFramework.Toolbox.GetDeviceDate (cmd.Device),
					Completed = (op) => {
						if (op.Success) {
							date = op.Date;
							setPropertyTime = DateTime.Now;
						} else {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to get date from device"));
							this.OnDebuggerOutput (true, op.GetOutput ());
						}
					},
				},
				new ChainedAsyncOperation<AndroidToolbox.AdbOutputOperation> () {
					Create = () => {
						this.OnDebuggerOutput (false, GettextCatalog.GetString ("Setting debug property") + "\n");
						long expireDate = date + (DEBUGGER_TIMEOUT_MS / 1000);
						string monoOptions = string.Format ("debug={0}:{1}:{2},timeout={3},server=y", dsi.Address, dsi.DebugPort, 0, expireDate);
						return MonoDroidFramework.Toolbox.SetProperty (cmd.Device, "debug.mono.extra", monoOptions);
					},
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to set debug property on device"));
							this.OnDebuggerOutput (true, op.GetOutput ());
						} else {
							debugPropertySet = true;
						}
					}
				},
				new ChainedAsyncOperation () {
					Skip = () => alreadyForwarded? "" : null,
					Create = () => {
						this.OnDebuggerOutput (false, GettextCatalog.GetString ("Forwarding debugger port") + "\n");
						return MonoDroidFramework.Toolbox.ForwardPort (cmd.Device, dsi.DebugPort, dsi.DebugPort, DebuggerOutput, DebuggerError);
					},
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to forward port on device"));
						}
					}
				},
				new ChainedAsyncOperation () {
					Skip = () => alreadyForwarded? "" : null,
					Create = () => {
						this.OnDebuggerOutput (false, GettextCatalog.GetString ("Forwarding console port") + "\n");
						return MonoDroidFramework.Toolbox.ForwardPort (cmd.Device, dsi.OutputPort, dsi.OutputPort, DebuggerOutput, DebuggerError);
					},
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to forward port on device"));
						} else {
							MonoDroidFramework.DeviceManager.SetDeviceLastForwarded (cmd.Device.ID);
						}
					}
				},
				new ChainedAsyncOperation<AdbGetProcessIdOperation> () {
					Create = () => new AdbGetProcessIdOperation (cmd.Device, cmd.PackageName),
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, "Error trying to detect already running process");
						} else if (op.ProcessId > 0) {
							this.OnDebuggerOutput (false, GettextCatalog.GetString ("Already running activity detected, restarting it in debug mode") + "\n");
							runningProcessId = op.ProcessId;
						}
					}
				},
				new ChainedAsyncOperation () {
					Skip = () => runningProcessId <= 0 ? "" : null,
					Create = () => new AdbShellOperation (cmd.Device, "kill " + runningProcessId),
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to stop already running activity"));
						}
					}
				},
				new ChainedAsyncOperation () {
					Create = () => MonoDroidFramework.Toolbox.StartActivity (cmd.Device, cmd.Activity, DebuggerOutput, DebuggerError),
					Completed = (op) => {
						if (!op.Success)
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to start activity"));
					}
				}
			);
			launchOp.Completed += delegate (IAsyncOperation op) {
				if (!op.Success) {
					EndSession ();
					return;
				}
				launchOp = null;
					
				Action<string> stdout = s => OnTargetOutput (false, s);
				Action<string> stderr = s => OnTargetOutput (true, s);

				trackProcessOp = new MonoDroidProcess (cmd.Device, cmd.Activity, cmd.PackageName, stdout, stderr);
				trackProcessOp.Completed += delegate {
					EndSession ();
				};
			
				System.Threading.Thread.Sleep (WAIT_BEFORE_CONNECT_MS);
				
				var msSinceSetProperty = (long) Math.Floor ((DateTime.Now - setPropertyTime).TotalMilliseconds);
				long msTillPropertyExpires = DEBUGGER_TIMEOUT_MS - msSinceSetProperty;
				
				if (msTillPropertyExpires < 100 || msTillPropertyExpires > DEBUGGER_TIMEOUT_MS)
					return;
				
				int retries = (int) Math.Floor ((double)  msTillPropertyExpires / WAIT_BEFORE_RETRY_MS) - 2;
				
				StartConnecting (dsi, retries, WAIT_BEFORE_RETRY_MS);
			};
			
			TargetExited += delegate {
				EndLaunch ();
			};
			
			launchOp.Start ();
		}
		void EndLaunch ()
		{
			if (alreadyEnded)
				return;
			alreadyEnded = true;

			if (launchOp != null && !launchOp.IsCompleted) {
				try {
					launchOp.Cancel ();
					launchOp = null;
				} catch {}
			}

			if (trackProcessOp != null && !trackProcessOp.IsCompleted) {
				// This operation should finish by itself, but make sure it's actually done.
				try {
					trackProcessOp.Cancel ();
					trackProcessOp = null;
				} catch {}
			}

			if (debugPropertySet) {
				try {
					MonoDroidFramework.Toolbox.SetProperty (debugDevice, "debug.mono.extra", String.Empty);
				} catch {}
			}
		}
		void EndLaunch ()
		{
			if (launchOp == null)
				return;
			if (!launchOp.IsCompleted) {
				try {
					launchOp.Cancel ();
					launchOp = null;
				} catch {}
			}
		}
Пример #7
0
		protected override void OnRun (DebuggerStartInfo startInfo)
		{
			var dsi = (MonoDroidDebuggerStartInfo) startInfo;
			var cmd = dsi.ExecutionCommand;
			
			long date = 0;
			launchOp = new ChainedAsyncOperationSequence (
				new ChainedAsyncOperation<AndroidToolbox.GetDateOperation> () {
					Create = () => MonoDroidFramework.Toolbox.GetDeviceDate (cmd.Device),
					Completed = (op) => {
						if (op.Success) {
							date = op.Date;
						} else {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to get date from device"));
							this.OnDebuggerOutput (true, op.GetOutput ());
						}
					},
				},
				new ChainedAsyncOperation<AndroidToolbox.AdbOutputOperation> () {
					Create = () => {
						long expireDate = date + 30; // 30 seconds
						string monoOptions = string.Format ("debug={0}:{1}:{2},timeout={3},server=y", dsi.Address, dsi.DebugPort, 0, expireDate);
						return MonoDroidFramework.Toolbox.SetProperty (cmd.Device, "debug.mono.extra", monoOptions);
					},
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to set debug property on device"));
							this.OnDebuggerOutput (true, op.GetOutput ());
						}
					}
				},
				new ChainedAsyncOperation () {
					Create = () => MonoDroidFramework.Toolbox.ForwardPort (cmd.Device, dsi.DebugPort, dsi.DebugPort, null, null),
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to forward port on device"));
						}
					}
				},
				new ChainedAsyncOperation () {
					Create = () => MonoDroidFramework.Toolbox.ForwardPort (cmd.Device, dsi.OutputPort, dsi.OutputPort, null, null),
					Completed = (op) => {
						if (!op.Success) {
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to forward port on device"));
						}
					}
				},
				new ChainedAsyncOperation () {
					Create = () => MonoDroidFramework.Toolbox.StartActivity (cmd.Device, cmd.Activity,
						(s, m) => OnTargetOutput (false, m),
						(s, m) => OnTargetOutput (true, m)
					),
					Completed = (op) => {
						if (!op.Success)
							this.OnDebuggerOutput (true, GettextCatalog.GetString ("Failed to start activity"));
					}
				}
			);
			launchOp.Completed += delegate(IAsyncOperation op) {
				if (!op.Success)
					EndSession ();
				launchOp = null;
			};
			
			TargetExited += delegate {
				EndLaunch ();
			};
			
			launchOp.Start ();
			
			// Connect to the process, giving it a time to start.
			System.Threading.Thread.Sleep (200);

			StartConnecting (dsi, -1, 800);
		}