diff --git a/src/Microsoft.Android.Run/Program.cs b/src/Microsoft.Android.Run/Program.cs index e0366f92066..06727724750 100644 --- a/src/Microsoft.Android.Run/Program.cs +++ b/src/Microsoft.Android.Run/Program.cs @@ -14,6 +14,7 @@ string? deviceUserId = null; string? instrumentation = null; bool verbose = false; +bool wakeDevice = true; int? logcatPid = null; Process? logcatProcess = null; CancellationTokenSource cts = new (); @@ -72,6 +73,9 @@ async Task RunAsync (string[] args) { "v|verbose", "Enable verbose output for debugging.", v => verbose = v != null }, + { "no-wake-device", + "Do not wake the device or dismiss its keyguard before launching the application.", + v => wakeDevice = v == null }, { "logcat-args=", "Extra {ARGUMENTS} to pass to 'adb logcat' (e.g., 'monodroid-assembly:S' to silence a tag).", v => logcatArgs = v }, @@ -515,7 +519,9 @@ async Task RunAppAsync () async Task StartAppAsync () { var userArg = string.IsNullOrEmpty (deviceUserId) ? "" : $" --user {deviceUserId}"; - var cmdArgs = $"shell am start -S -W{userArg} -n \"{package}/{activity}\""; + // Device preparation is best effort; am start must run and determine the shell exit code. + var wakeDeviceCommand = wakeDevice ? "input keyevent KEYCODE_WAKEUP; wm dismiss-keyguard; " : ""; + var cmdArgs = $"shell {wakeDeviceCommand}am start -S -W{userArg} -n \"{package}/{activity}\""; var (exitCode, output, error) = await AdbHelper.RunAsync (adbPath, adbTarget, cmdArgs, cts.Token, verbose); if (exitCode != 0) { Console.Error.WriteLine ($"Error: Failed to start app: {error}"); diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 8a8c5355db1..57c01d83683 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -341,14 +341,15 @@ static int InvokeIntMethod (Java.Lang.Object instance, string methodName) Assert.True (builder.Uninstall (proj), "Project should have uninstalled."); } - [Test] - public void DotNetRunWaitForExit () + [TestCase ("", true)] + [TestCase ("--no-wake-device", false)] + public void DotNetRunWaitForExit (string extraArgs, bool shouldWakeDevice) { const string logcatMessage = "DOTNET_RUN_TEST_MESSAGE_12345"; var proj = new XamarinAndroidApplicationProject (); // Enable verbose output from Microsoft.Android.Run for debugging - proj.SetProperty ("_AndroidRunExtraArgs", "--verbose"); + proj.SetProperty ("_AndroidRunExtraArgs", $"--verbose {extraArgs}"); // Add a Console.WriteLine that will appear in logcat proj.MainActivity = proj.DefaultMainActivity.Replace ( @@ -401,10 +402,22 @@ public void DotNetRunWaitForExit () } // Write the output to a log file for debugging - string logPath = Path.Combine (Root, builder.ProjectDirectory, "dotnet-run-output.log"); - File.WriteAllText (logPath, output.ToString ()); + string outputText = output.ToString (); + string logPath = Path.Combine (Root, builder.ProjectDirectory, $"dotnet-run-output-wake-{shouldWakeDevice}.log"); + File.WriteAllText (logPath, outputText); TestContext.AddTestAttachment (logPath); + if (shouldWakeDevice) { + StringAssert.Contains ("shell input keyevent KEYCODE_WAKEUP; wm dismiss-keyguard; am start", outputText, + $"`dotnet run` should wake the device and dismiss its keyguard in the same adb shell command used to start the app. See {logPath} for details."); + } else { + StringAssert.Contains ("shell am start", outputText, + $"`dotnet run` should start the app without waking the device or dismissing its keyguard when --no-wake-device is specified. See {logPath} for details."); + StringAssert.DoesNotContain ("KEYCODE_WAKEUP", outputText, + $"`dotnet run` should not wake the device when --no-wake-device is specified. See {logPath} for details."); + StringAssert.DoesNotContain ("dismiss-keyguard", outputText, + $"`dotnet run` should not dismiss the keyguard when --no-wake-device is specified. See {logPath} for details."); + } Assert.IsTrue (foundMessage, $"Expected message '{logcatMessage}' was not found in output. See {logPath} for details."); }