Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tests] Add support for testing on system appli…
Browse files Browse the repository at this point in the history
…cations. (#5708)

Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1288717
Context: xamarin/monodroid@83de4b4

The new fast deployment system (xamarin/monodroid@767f6471) broke
fast deployment for system-installed applications.

This is fixed in xamarin/monodroid@83de4b43.

Adds unit tests to stop this kind of regression in the future.

In order to install a `system` application we need a few things:

 1. The emulator MUST be started with the `-system-writable` argument

 2. The `.apk` needs to be signed with a platform keystore, found at:
    https://github.com/aosp-mirror/platform_build/tree/master/target/product/security

 3. `AndroidManifest.xml` must set
    [`/manifest/@android:sharedUserId`][0] to `android.uid.system`:

        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            android:sharedUserId="android.uid.system"
            …>
        </manifest>

See also:

  * https://medium.com/xrpractices/android-system-apps-development-d73bedfb8def

[0]: https://developer.android.com/guide/topics/manifest/manifest-element#uid
  • Loading branch information
dellis1972 committed Mar 24, 2021
1 parent d9ed129 commit 2a04748
Show file tree
Hide file tree
Showing 30 changed files with 265 additions and 88 deletions.
14 changes: 14 additions & 0 deletions Documentation/guides/building-apps/build-properties.md
Expand Up @@ -1041,6 +1041,20 @@ To use a file located at `C:\Users\user1\AndroidSigningPassword.txt`:
> The `env:` prefix is not supported when [`$(AndroidPackageFormat)`](#androidpackageformat)
> is set to `aab`.
## AndroidSigningPlatformKey

Specifies the key file to use to sign the apk.
This is only used when building `system` applications.

Support for this property was added in Xamarin.Android 11.3.

## AndroidSigningPlatformCert

Specifies the certificate file to use to sign the apk.
This is only used when building `system` applications.

Support for this property was added in Xamarin.Android 11.3.

## AndroidSupportedAbis

A string property that contains a
Expand Down
11 changes: 4 additions & 7 deletions Documentation/guides/messages/xa4310.md
Expand Up @@ -8,17 +8,14 @@ ms.date: 03/09/2020
## Example messages

```
error XA4310: `$(AndroidSigningKeyStore)` file `filename.keystore` could not be found.
error XA4310: `$(Property)` file `filename.keystore` could not be found.
```

## Issue

The specified `$(AndroidSigningKeyStore)` file could not be located on disk.
The specified `$(Property)` file could not be located on disk.

## Solution

Check that the `$(AndroidSigningKeyStore)` MSBuild property is set to a valid
path of an existing keystore.

This property corresponds to the **Keystore** field in the **Android Package
Signing** section of the Visual Studio project property pages.
Check that the `$(Property)` MSBuild property is set to a valid
path of an existing file.
13 changes: 13 additions & 0 deletions Documentation/release-notes/5708.md
@@ -0,0 +1,13 @@
#### Application build and deployment

* [Developer Community 1288717][0]:
*Support Fast Deployment for System Applications.*
Added support for fast deployment while building system based
applications. Applications developed in this mode need to be
signed with a platform key and have a special attribute

`android:sharedUserId="android.uid.system"`

in the `AndroidManifest.xml`.

[0]: https://developercommunity.visualstudio.com/t/VS-2019-1690-Error-XA0130-XamarinAndr/1359238
Expand Up @@ -20,6 +20,7 @@ public class StartAndroidEmulator : Task
public string AndroidSdkHome {get; set;}
public string Port {get; set;}
public string ImageName {get; set;} = "XamarinAndroidTestRunner64";
public string Arguments {get; set;}
public string ToolPath {get; set;}
public string ToolExe {get; set;}

Expand Down Expand Up @@ -62,7 +63,7 @@ void Run (string emulator)
return;

var port = string.IsNullOrEmpty (Port) ? "" : $" -port {Port}";
var arguments = $"-verbose -no-boot-anim -no-audio -no-snapshot -cache-size 512 -timezone \"Etc/UTC\" -avd {ImageName}{port}";
var arguments = $"{Arguments ?? string.Empty} -verbose -no-boot-anim -no-audio -no-snapshot -cache-size 512 -timezone \"Etc/UTC\" -avd {ImageName}{port}";
Log.LogMessage (MessageImportance.Low, $"Tool {emulator} execution started with arguments: {arguments}");
var psi = new ProcessStartInfo () {
FileName = emulator,
Expand Down
2 changes: 2 additions & 0 deletions build-tools/automation/azure-pipelines-nightly.yaml
Expand Up @@ -173,3 +173,5 @@ stages:
- template: yaml-templates/run-timezoneinfo-tests.yaml
parameters:
node_id: 4

- template: yaml-templates/run-systemapp-tests.yaml
2 changes: 1 addition & 1 deletion build-tools/automation/azure-pipelines.yaml
Expand Up @@ -63,7 +63,7 @@ variables:
# - This is a non-fork branch with name containing "mono-" (for Mono bumps)
IsMonoBranch: $[and(ne(variables['System.PullRequest.IsFork'], 'True'), or(contains(variables['Build.SourceBranchName'], 'mono-'), contains(variables['System.PullRequest.SourceBranch'], 'mono-')))]
RunAllTests: $[or(eq(variables['XA.RunAllTests'], true), eq(variables['IsMonoBranch'], true))]
DotNetNUnitCategories: '& TestCategory != DotNetIgnore & TestCategory != AOT & TestCategory != MkBundle & TestCategory != MonoSymbolicate & TestCategory != PackagesConfig & TestCategory != StaticProject & TestCategory != Debugger'
DotNetNUnitCategories: '& TestCategory != DotNetIgnore & TestCategory != AOT & TestCategory != MkBundle & TestCategory != MonoSymbolicate & TestCategory != PackagesConfig & TestCategory != StaticProject & TestCategory != Debugger & TestCategory != SystemApplication'
NUnit.NumberOfTestWorkers: 4
GitHub.Token: $(github--pat--vs-mobiletools-engineering-service2)
CONVERT_JAVADOC_TO_XMLDOC: $[ne(variables['Build.DefinitionName'], 'Xamarin.Android-PR')]
Expand Down
Expand Up @@ -60,7 +60,7 @@ jobs:
useDotNet: $(UseDotNet)
testRunTitle: MSBuildDeviceIntegration On Device - macOS - ${{ parameters.job_suffix }}
testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/MSBuildDeviceIntegration/${{ parameters.target_framework }}/MSBuildDeviceIntegration.dll
nunitConsoleExtraArgs: --where "cat != TimeZoneInfo && cat != SmokeTests ${{ parameters.nunit_categories }}"
nunitConsoleExtraArgs: --where "cat != SystemApplication && cat != TimeZoneInfo && cat != SmokeTests ${{ parameters.nunit_categories }}"
dotNetTestExtraArgs: --filter "TestCategory != TimeZoneInfo & TestCategory != SmokeTests ${{ parameters.nunit_categories }}"
testResultsFile: TestResult-MSBuildDeviceIntegration-${{ parameters.job_name }}-$(XA.Build.Configuration).xml

Expand Down
52 changes: 52 additions & 0 deletions build-tools/automation/yaml-templates/run-systemapp-tests.yaml
@@ -0,0 +1,52 @@
# Runs TimeZoneInfo tests against an emulator running on macOS

jobs:
- job: mac_systemapp_tests
displayName: System App Emulator Tests
pool:
vmImage: $(HostedMacImage)
timeoutInMinutes: 120
cancelTimeoutInMinutes: 5
workspace:
clean: all
steps:
- template: setup-test-environment.yaml

- script: mono $(System.DefaultWorkingDirectory)/build-tools/xaprepare/xaprepare/bin/$(XA.Build.Configuration)/xaprepare.exe --s=EmulatorTestDependencies --no-emoji --run-mode=CI
displayName: install emulator

- task: DownloadPipelineArtifact@2
inputs:
artifactName: $(TestAssembliesArtifactName)
downloadPath: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)

- task: MSBuild@1
displayName: start emulator
inputs:
solution: tests/Mono.Android-Tests/Mono.Android-Tests.csproj
configuration: $(XA.Build.Configuration)
msbuildArguments: >-
/t:AcquireAndroidTarget /p:TestEmulatorArguments=-writable-system /bl:$(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/start-emulator.binlog
- template: run-nunit-tests.yaml
parameters:
testRunTitle: System App On Device - macOS
testAssembly: $(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/MSBuildDeviceIntegration/net472/MSBuildDeviceIntegration.dll
nunitConsoleExtraArgs: --where "cat == SystemApplication"
testResultsFile: TestResult-SystemApp--$(XA.Build.Configuration).xml

- task: MSBuild@1
displayName: shut down emulator
inputs:
solution: tests/Mono.Android-Tests/Mono.Android-Tests.csproj
configuration: $(XA.Build.Configuration)
msbuildArguments: >-
/t:AcquireAndroidTarget,ReleaseAndroidTarget
/bl:$(System.DefaultWorkingDirectory)/bin/Test$(XA.Build.Configuration)/shutdown-emulator.binlog
condition: always()

- template: upload-results.yaml
parameters:
artifactName: Test Results - System App With Emulator - macOS

- template: fail-on-issue.yaml
1 change: 1 addition & 0 deletions build-tools/scripts/TestApks.targets
Expand Up @@ -65,6 +65,7 @@
<StartAndroidEmulator
Condition=" '$(_ValidAdbTarget)' != 'True' "
AndroidSdkHome="$(AndroidSdkDirectory)"
Arguments="$(TestEmulatorArguments)"
ImageName="$(TestAvdName)"
Port="$(_AdbEmulatorPort)"
ToolExe="$(EmulatorToolExe)"
Expand Down
6 changes: 4 additions & 2 deletions src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
Expand Up @@ -712,8 +712,10 @@ The following are literal names and should not be translated: ABI, 'libs/armeabi
<comment>The following are literal names and should not be translated: MultiDexMainDexList</comment>
</data>
<data name="XA4310" xml:space="preserve">
<value>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</value>
<comment>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</comment>
<value>`{0}` file `{1}` could not be found.</value>
<comment>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</comment>
</data>
<data name="XA4311" xml:space="preserve">
<value>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</value>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">Soubor $(AndroidSigningKeyStore) {0} se nepovedlo najít.</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="needs-review-translation">Soubor {0} {1} se nepovedlo najít.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">Die $(AndroidSigningKeyStore)-Datei "{0}" wurde nicht gefunden.</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="needs-review-translation">Die {0}-Datei "{1}" wurde nicht gefunden.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">No se ha encontrado el archivo "{0}" de "$(AndroidSigningKeyStore)".</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="needs-review-translation">No se ha encontrado el archivo "{1}" de "{0}".</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">Le fichier '$(AndroidSigningKeyStore)' '{0}' est introuvable.</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="needs-review-translation">Le fichier '{0}' '{1}' est introuvable.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">Non è stato possibile trovare il file `{0}` di `$(AndroidSigningKeyStore)`.</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="needs-review-translation">Non è stato possibile trovare il file `{1}` di `{0}`.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">'$(AndroidSigningKeyStore)' ファイル '{0}' が見つかりませんでした。</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="needs-review-translation">'{0}' ファイル '{1}' が見つかりませんでした。</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">'$(AndroidSigningKeyStore)' 파일 '{0}'을(를) 찾을 수 없습니다.</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="needs-review-translation">'{0}' 파일 '{1}'을(를) 찾을 수 없습니다.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">Nie można odnaleźć pliku „$(AndroidSigningKeyStore)” („{0}”).</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="new">`{0}` file `{1}` could not be found.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">Não foi possível localizar o arquivo `{0}` de `$(AndroidSigningKeyStore)`.</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="new">`{0}` file `{1}` could not be found.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down
Expand Up @@ -744,9 +744,11 @@ In this message, "root element" refers to the root element of an XML file.
<note>The following are literal names and should not be translated: MultiDexMainDexList</note>
</trans-unit>
<trans-unit id="XA4310">
<source>`$(AndroidSigningKeyStore)` file `{0}` could not be found.</source>
<target state="translated">Не удалось найти файл "$(AndroidSigningKeyStore)" с именем "{0}".</target>
<note>The following are literal names and should not be translated: `$(AndroidSigningKeyStore)`</note>
<source>`{0}` file `{1}` could not be found.</source>
<target state="new">`{0}` file `{1}` could not be found.</target>
<note>{0} - The MSBuildProperty which contains the file name value.
{1} - The value of the MSBuildProperty. Normally a filename.
</note>
</trans-unit>
<trans-unit id="XA4311">
<source>The application won't contain the paired Wear package because the Wear application package APK is not created yet. If building on the command line, be sure to build the "SignAndroidPackage" target.</source>
Expand Down

0 comments on commit 2a04748

Please sign in to comment.