Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .external
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
xamarin/monodroid:master@0eef889156e92ff0d47e62477f10798b6d5b5c29
xamarin/monodroid:master@27736a7ffc48d606ab45598f761e873f8572f46a
mono/mono:2020-02@ac596375c762c6b8dbe3c802f0ce626004eab51c
24 changes: 24 additions & 0 deletions Documentation/guides/building-apps/build-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,30 @@ to `pkcs12`.

Added in Xamarin.Android 10.2.


## AndroidDeviceUserId

Allows deploying and debugging the application under guest
or work accounts. The value is the `uid` value you get
from the following adb command

```
adb shell pm list users
```

This will return the following data

```
Users:
UserInfo{0:Owner:c13} running
UserInfo{10:Guest:404}
```

The `uid` is the first integer value. In the example they
are `0` and `10`.

Added in Xamarin.Android 11.2

## AndroidDexTool

An enum-style property with valid
Expand Down
33 changes: 33 additions & 0 deletions Documentation/release-notes/5311.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
### Build and deployment performance

* [GitHub PR 5311](https://github.com/xamarin/xamarin-android/pull/5311):
Add support for deploying and debugging against different user accounts
on Android Devices. In order to use this you need to specify the
`AndroidDeviceUserId` in either your csproj or on the command line.

```xml
<PropertyGroup>
<AndroidDeviceUserId>10</AndroidDeviceUserId>
</PropertyGroup>
```

```
msbuild foo.csproj /t:Install /p:AndroidDeviceUserId=10
```

The value is the `uid` value you get from the following adb command

```
adb shell pm list users
```

This will return the following data

```
Users:
UserInfo{0:Owner:c13} running
UserInfo{10:Guest:404}
```

The `uid` is the first integer value. In the example they
are `0` and `10`.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ namespace Xamarin.Android.Build.Tests
{
public class DeviceTest: BaseTest
{
public const string GuestUserName = "guest1";

[OneTimeSetUp]
public void DeviceSetup ()
{
SetAdbLogcatBufferSize (64);
RunAdbCommand ("logcat -c");
CreateGuestUser (GuestUserName);
}

[TearDown]
Expand All @@ -42,6 +45,7 @@ protected override void CleanupTest ()

ClearAdbLogcat ();


base.CleanupTest ();
}

Expand Down Expand Up @@ -260,5 +264,42 @@ protected static string [] GetOverrideDirectoryPaths (string packageName)
$"/storage/sdcard/Android/data/{packageName}/files/.__override__",
};
}

protected static void CreateGuestUser (string username)
{
if (GetUserId (username) != -1)
RunAdbCommand ($"shell pm create-user --guest {username}");
}

protected static void DeleteGuestUser (string username)
{
int userId = GetUserId (username);
if (userId > 0)
RunAdbCommand ($"shell pm remove-user --guest {userId}");
}

protected static int GetUserId (string username)
{
string output = RunAdbCommand ($"shell pm list users");
Regex regex = new Regex (@"UserInfo{(?<userId>\d+):" + username, RegexOptions.Compiled);
Console.WriteLine (output);
var match = regex.Match (output);
if (match.Success) {
return int.Parse (match.Groups ["userId"].Value);
}
return -1;
}

protected static bool SwitchUser (string username)
{
int userId = GetUserId (username);
if (userId == -1)
userId = 0;
if (userId >= 0) {
RunAdbCommand ($"shell am switch-user {userId}");
return true;
}
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
if (Builder.UseDotNet) {
SetProperty (KnownProperties.OutputType, "Exe");
SetProperty ("XamarinAndroidSupportSkipVerifyVersions", "True");
SetProperty ("_FastDeploymentDiagnosticLogging", "True");

// Workaround for AndroidX, see: https://github.com/xamarin/AndroidSupportComponents/pull/239
Imports.Add (new Import (() => "Directory.Build.targets") {
Expand All @@ -51,6 +52,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
</Project>"
});
} else {
SetProperty ("_FastDeploymentDiagnosticLogging", "True");
SetProperty ("AndroidApplication", "True");
SetProperty ("AndroidResgenClass", "Resource");
SetProperty ("AndroidResgenFile", () => "Resources\\Resource.designer" + Language.DefaultDesignerExtension);
Expand Down
1 change: 1 addition & 0 deletions tests/MSBuildDeviceIntegration/Tests/BundleToolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ public void ApkSet ()
{
AssertHasDevices ();

appBuilder.BuildLogFile = "install.log";
Assert.IsTrue (appBuilder.RunTarget (app, "Install"), "App should have installed.");

var aab = Path.Combine (intermediate, "android", "bin", "UnnamedProject.UnnamedProject.apks");
Expand Down
44 changes: 37 additions & 7 deletions tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Mono.Debugging.Soft;
using NUnit.Framework;
using Xamarin.ProjectTools;
using System.Collections.Generic;

namespace Xamarin.Android.Build.Tests
{
Expand Down Expand Up @@ -251,36 +252,63 @@ public override void OnCreate ()
/* embedAssemblies */ true,
/* fastDevType */ "Assemblies",
/* allowDeltaInstall */ false,
/* user */ null,
},
new object[] {
/* embedAssemblies */ false,
/* fastDevType */ "Assemblies",
/* allowDeltaInstall */ false,
/* user */ null,
},
new object[] {
/* embedAssemblies */ false,
/* fastDevType */ "Assemblies",
/* allowDeltaInstall */ true,
/* user */ null,
},
new object[] {
/* embedAssemblies */ false,
/* fastDevType */ "Assemblies:Dexes",
/* allowDeltaInstall */ false,
/* user */ null,
},
new object[] {
/* embedAssemblies */ false,
/* fastDevType */ "Assemblies:Dexes",
/* allowDeltaInstall */ true,
/* user */ null,
},
new object[] {
/* embedAssemblies */ true,
/* fastDevType */ "Assemblies",
/* allowDeltaInstall */ false,
/* user */ DeviceTest.GuestUserName,
},
new object[] {
/* embedAssemblies */ false,
/* fastDevType */ "Assemblies",
/* allowDeltaInstall */ false,
/* user */ DeviceTest.GuestUserName,
},
};
#pragma warning restore 414

[Test, Category ("SmokeTests"), Category ("Debugger")]
[TestCaseSource (nameof(DebuggerTestCases))]
public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall)
public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username)
{
AssertCommercialBuild ();
AssertHasDevices ();

int userId = GetUserId (username);
List<string> parameters = new List<string> ();
if (userId >= 0)
parameters.Add ($"AndroidDeviceUserId={userId}");
if (SwitchUser (username)) {
WaitFor (5);
ClickButton ("", "android:id/button1", "Yes continue");
}

var proj = new XamarinFormsAndroidApplicationProject () {
IsRelease = false,
EmbedAssembliesIntoApk = embedAssemblies,
Expand All @@ -291,7 +319,7 @@ public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string f
proj.SetDefaultTargetDevice ();
using (var b = CreateApkBuilder (Path.Combine ("temp", TestName))) {
SetTargetFrameworkAndManifest (proj, b);
Assert.True (b.Install (proj), "Project should have installed.");
Assert.True (b.Install (proj, parameters: parameters.ToArray ()), "Project should have installed.");

int breakcountHitCount = 0;
ManualResetEvent resetEvent = new ManualResetEvent (false);
Expand Down Expand Up @@ -324,11 +352,13 @@ public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string f
options.EvaluationOptions.UseExternalTypeResolver = true;
ClearAdbLogcat ();
b.BuildLogFile = "run.log";
Assert.True (b.RunTarget (proj, "_Run", doNotCleanupOnUpdate: true, parameters: new string [] {
$"AndroidSdbTargetPort={port}",
$"AndroidSdbHostPort={port}",
"AndroidAttachDebugger=True",
}), "Project should have run.");

parameters.Add ($"AndroidSdbTargetPort={port}");
parameters.Add ($"AndroidSdbHostPort={port}");
parameters.Add ("AndroidAttachDebugger=True");

Assert.True (b.RunTarget (proj, "_Run", doNotCleanupOnUpdate: true,
parameters: parameters.ToArray ()), "Project should have run.");

Assert.IsTrue (WaitForDebuggerToStart (Path.Combine (Root, b.ProjectDirectory, "logcat.log")), "Activity should have started");
// we need to give a bit of time for the debug server to start up.
Expand Down