Skip to content

Commit 7b51fd1

Browse files
authored
Bump to xamarin/monodroid@27736a7f; add multi-user tests (#5311)
Context: #5331 Changes: xamarin/monodroid@0eef889...27736a7 * xamarin/monodroid@27736a7ff: [tools/msbuild] Fix App Bundle deployment (#1142) * xamarin/monodroid@f38dbc7ab: [tools/msbuild] use @(_AndroidMSBuildAllProjects) (#1140) * xamarin/monodroid@cfa21d57b: [tools/msbuild] Fix some issues with FastDev (#1139) * xamarin/monodroid@3ba648386: [tools/msbuild] Add missing parameter to BuildAppBundle. (#1138) * xamarin/monodroid@5bb29971b: [tools/msbuild] Add Multi User Support for Debugging. (#1135) * xamarin/monodroid@156abf47c: [tools/msbuild] default $(_AndroidAllowDeltaInstall) to false (#1137) * xamarin/monodroid@fbc961218: [build] Pass EnableCompression to BuildApk (#1094) Add support for running multi-user unit tests on device. It makes use of various adb commands to create test users and remove them. Create a guest user with name `{name}`: adb shell pm create-user --guest {name} Remove a guest user with the specified user id `{userId}`: adb shell pm remove-user --guest {userId} Note that user creation takes a "name", while deletion takes an id. To obtain the mapping, use: $ adb shell pm list users Users: UserInfo{0:Owner:c13} running UserInfo{10:guest1:414} The userId is the number *between* the `{` and the `:` and user name. The userId for `Owner` is 0, while the userId for `guest1` is 10. We can then use a `Regex` to pull out the required `userId` for a specific user. To switch a device to use user `{userId}`: adb shell am switch-user {userId} Emulators seem to create the main user with the name "Owner", so that should be the default name we use for the main user. In the unit tests if we cannot find a user named "Owner" when looking for "Owner" we will default to a `userId` of `0`. User ID 0 always means the default user. This is to handle the case where we are testing locally on devices where the main user is not called "Owner".
1 parent 7808c01 commit 7b51fd1

File tree

7 files changed

+139
-8
lines changed

7 files changed

+139
-8
lines changed

.external

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
xamarin/monodroid:master@0eef889156e92ff0d47e62477f10798b6d5b5c29
1+
xamarin/monodroid:master@27736a7ffc48d606ab45598f761e873f8572f46a
22
mono/mono:2020-02@ac596375c762c6b8dbe3c802f0ce626004eab51c

Documentation/guides/building-apps/build-properties.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,30 @@ to `pkcs12`.
274274

275275
Added in Xamarin.Android 10.2.
276276

277+
278+
## AndroidDeviceUserId
279+
280+
Allows deploying and debugging the application under guest
281+
or work accounts. The value is the `uid` value you get
282+
from the following adb command
283+
284+
```
285+
adb shell pm list users
286+
```
287+
288+
This will return the following data
289+
290+
```
291+
Users:
292+
UserInfo{0:Owner:c13} running
293+
UserInfo{10:Guest:404}
294+
```
295+
296+
The `uid` is the first integer value. In the example they
297+
are `0` and `10`.
298+
299+
Added in Xamarin.Android 11.2
300+
277301
## AndroidDexTool
278302

279303
An enum-style property with valid
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
### Build and deployment performance
2+
3+
* [GitHub PR 5311](https://github.com/xamarin/xamarin-android/pull/5311):
4+
Add support for deploying and debugging against different user accounts
5+
on Android Devices. In order to use this you need to specify the
6+
`AndroidDeviceUserId` in either your csproj or on the command line.
7+
8+
```xml
9+
<PropertyGroup>
10+
<AndroidDeviceUserId>10</AndroidDeviceUserId>
11+
</PropertyGroup>
12+
```
13+
14+
```
15+
msbuild foo.csproj /t:Install /p:AndroidDeviceUserId=10
16+
```
17+
18+
The value is the `uid` value you get from the following adb command
19+
20+
```
21+
adb shell pm list users
22+
```
23+
24+
This will return the following data
25+
26+
```
27+
Users:
28+
UserInfo{0:Owner:c13} running
29+
UserInfo{10:Guest:404}
30+
```
31+
32+
The `uid` is the first integer value. In the example they
33+
are `0` and `10`.

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/DeviceTest.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ namespace Xamarin.Android.Build.Tests
1313
{
1414
public class DeviceTest: BaseTest
1515
{
16+
public const string GuestUserName = "guest1";
17+
1618
[OneTimeSetUp]
1719
public void DeviceSetup ()
1820
{
1921
SetAdbLogcatBufferSize (64);
2022
RunAdbCommand ("logcat -c");
23+
CreateGuestUser (GuestUserName);
2124
}
2225

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

4346
ClearAdbLogcat ();
4447

48+
4549
base.CleanupTest ();
4650
}
4751

@@ -260,5 +264,42 @@ protected static string [] GetOverrideDirectoryPaths (string packageName)
260264
$"/storage/sdcard/Android/data/{packageName}/files/.__override__",
261265
};
262266
}
267+
268+
protected static void CreateGuestUser (string username)
269+
{
270+
if (GetUserId (username) != -1)
271+
RunAdbCommand ($"shell pm create-user --guest {username}");
272+
}
273+
274+
protected static void DeleteGuestUser (string username)
275+
{
276+
int userId = GetUserId (username);
277+
if (userId > 0)
278+
RunAdbCommand ($"shell pm remove-user --guest {userId}");
279+
}
280+
281+
protected static int GetUserId (string username)
282+
{
283+
string output = RunAdbCommand ($"shell pm list users");
284+
Regex regex = new Regex (@"UserInfo{(?<userId>\d+):" + username, RegexOptions.Compiled);
285+
Console.WriteLine (output);
286+
var match = regex.Match (output);
287+
if (match.Success) {
288+
return int.Parse (match.Groups ["userId"].Value);
289+
}
290+
return -1;
291+
}
292+
293+
protected static bool SwitchUser (string username)
294+
{
295+
int userId = GetUserId (username);
296+
if (userId == -1)
297+
userId = 0;
298+
if (userId >= 0) {
299+
RunAdbCommand ($"shell am switch-user {userId}");
300+
return true;
301+
}
302+
return false;
303+
}
263304
}
264305
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
4040
if (Builder.UseDotNet) {
4141
SetProperty (KnownProperties.OutputType, "Exe");
4242
SetProperty ("XamarinAndroidSupportSkipVerifyVersions", "True");
43+
SetProperty ("_FastDeploymentDiagnosticLogging", "True");
4344

4445
// Workaround for AndroidX, see: https://github.com/xamarin/AndroidSupportComponents/pull/239
4546
Imports.Add (new Import (() => "Directory.Build.targets") {
@@ -51,6 +52,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
5152
</Project>"
5253
});
5354
} else {
55+
SetProperty ("_FastDeploymentDiagnosticLogging", "True");
5456
SetProperty ("AndroidApplication", "True");
5557
SetProperty ("AndroidResgenClass", "Resource");
5658
SetProperty ("AndroidResgenFile", () => "Resources\\Resource.designer" + Language.DefaultDesignerExtension);

tests/MSBuildDeviceIntegration/Tests/BundleToolTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ public void ApkSet ()
253253
{
254254
AssertHasDevices ();
255255

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

258259
var aab = Path.Combine (intermediate, "android", "bin", "UnnamedProject.UnnamedProject.apks");

tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Mono.Debugging.Soft;
99
using NUnit.Framework;
1010
using Xamarin.ProjectTools;
11+
using System.Collections.Generic;
1112

1213
namespace Xamarin.Android.Build.Tests
1314
{
@@ -251,36 +252,63 @@ public override void OnCreate ()
251252
/* embedAssemblies */ true,
252253
/* fastDevType */ "Assemblies",
253254
/* allowDeltaInstall */ false,
255+
/* user */ null,
254256
},
255257
new object[] {
256258
/* embedAssemblies */ false,
257259
/* fastDevType */ "Assemblies",
258260
/* allowDeltaInstall */ false,
261+
/* user */ null,
259262
},
260263
new object[] {
261264
/* embedAssemblies */ false,
262265
/* fastDevType */ "Assemblies",
263266
/* allowDeltaInstall */ true,
267+
/* user */ null,
264268
},
265269
new object[] {
266270
/* embedAssemblies */ false,
267271
/* fastDevType */ "Assemblies:Dexes",
268272
/* allowDeltaInstall */ false,
273+
/* user */ null,
269274
},
270275
new object[] {
271276
/* embedAssemblies */ false,
272277
/* fastDevType */ "Assemblies:Dexes",
273278
/* allowDeltaInstall */ true,
279+
/* user */ null,
280+
},
281+
new object[] {
282+
/* embedAssemblies */ true,
283+
/* fastDevType */ "Assemblies",
284+
/* allowDeltaInstall */ false,
285+
/* user */ DeviceTest.GuestUserName,
286+
},
287+
new object[] {
288+
/* embedAssemblies */ false,
289+
/* fastDevType */ "Assemblies",
290+
/* allowDeltaInstall */ false,
291+
/* user */ DeviceTest.GuestUserName,
274292
},
275293
};
276294
#pragma warning restore 414
277295

278296
[Test, Category ("SmokeTests"), Category ("Debugger")]
279297
[TestCaseSource (nameof(DebuggerTestCases))]
280-
public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall)
298+
public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username)
281299
{
282300
AssertCommercialBuild ();
283301
AssertHasDevices ();
302+
303+
int userId = GetUserId (username);
304+
List<string> parameters = new List<string> ();
305+
if (userId >= 0)
306+
parameters.Add ($"AndroidDeviceUserId={userId}");
307+
if (SwitchUser (username)) {
308+
WaitFor (5);
309+
ClickButton ("", "android:id/button1", "Yes continue");
310+
}
311+
284312
var proj = new XamarinFormsAndroidApplicationProject () {
285313
IsRelease = false,
286314
EmbedAssembliesIntoApk = embedAssemblies,
@@ -291,7 +319,7 @@ public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string f
291319
proj.SetDefaultTargetDevice ();
292320
using (var b = CreateApkBuilder (Path.Combine ("temp", TestName))) {
293321
SetTargetFrameworkAndManifest (proj, b);
294-
Assert.True (b.Install (proj), "Project should have installed.");
322+
Assert.True (b.Install (proj, parameters: parameters.ToArray ()), "Project should have installed.");
295323

296324
int breakcountHitCount = 0;
297325
ManualResetEvent resetEvent = new ManualResetEvent (false);
@@ -324,11 +352,13 @@ public void ApplicationRunsWithDebuggerAndBreaks (bool embedAssemblies, string f
324352
options.EvaluationOptions.UseExternalTypeResolver = true;
325353
ClearAdbLogcat ();
326354
b.BuildLogFile = "run.log";
327-
Assert.True (b.RunTarget (proj, "_Run", doNotCleanupOnUpdate: true, parameters: new string [] {
328-
$"AndroidSdbTargetPort={port}",
329-
$"AndroidSdbHostPort={port}",
330-
"AndroidAttachDebugger=True",
331-
}), "Project should have run.");
355+
356+
parameters.Add ($"AndroidSdbTargetPort={port}");
357+
parameters.Add ($"AndroidSdbHostPort={port}");
358+
parameters.Add ("AndroidAttachDebugger=True");
359+
360+
Assert.True (b.RunTarget (proj, "_Run", doNotCleanupOnUpdate: true,
361+
parameters: parameters.ToArray ()), "Project should have run.");
332362

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

0 commit comments

Comments
 (0)