Skip to content

Conversation

dellis1972
Copy link
Contributor

@dellis1972 dellis1972 commented May 15, 2020

Fixes #5009
Fixes #5147
Fixes #4996

The Fast Deployment system used for debugging Xamarin.Android
apps has been completely re-written. This is mostly due to
changes in the android OS which means we can no longer use
the external storage directory to store assemblies.

Fast Deployment works by not including files which change often,
like assemblies, in the actual apk. This means the .apk will
mostly not need to be re-installed during a debugging/development
session. Instead the assemblies are "Fast Deployed" to a special
directory where a debug version of our runtime knows where to find
them.

Historically this was on the external storage directory such as

`/storage/emulated/0/Android/data/com.some.package`
`/mnt/shell/emulated/0/Android/data/com.some.package`
`/storage/sdcard/Android/data/com.some.package`

With the advent of Android 11, these directories are no longer accessable.
So instead we need to deploy the assemblies into the app internal files
directory. This is usually located in /data/data/com.some.package. This
is not a global writable folder, so we need to use the run-as tool to
run all the commands to copy the files into that diectory.

The run-as tool does not always work on older devices. So from this point on
Fast Deployment will only be available on API 21 devices or newer. If a certain
device does not support the run-as tool, then you can always fall back to
debugging without Fast Deployment. While this is slower, it should still work
on most devices.

The Enhanced Fast Deployment mode is still available with this new system.
This will deploy both assemblies, native libraries, typemaps and dexes to the files
directory. Support for Fast Deploying resources and assets via that system was
removed in commit f0d565fe. This was becuase it required the use of
depreicated API's to work.

The Shared Runtime has also be removed in this new system. Before we used to deploy
the BCL and API specific assemblies via seperate .apks. This new system removes
the need for that. All the BCL and API specific assemblies will be deployed to the
files directory like all the other assemblies.

The new system is on par with the existing system when it comes to speed. More
improvements are planned in future releases which should make it much quicker.

Using the samples\HelloWorld project these are the performance differences
using HelloWorld.csproj /restore /t:Install /v:n

Old From Clean Time Elapsed 00:00:11.42
Old C# Change Time Elapsed 00:00:02.58

New From Clean Time Elapsed 00:00:11.78
New C# Change Time Elapsed 00:00:02.43

@dellis1972 dellis1972 force-pushed the fastdevv2 branch 2 times, most recently from cd83db6 to fa4a580 Compare May 20, 2020 09:36
@brendanzagaeski
Copy link
Contributor

Draft release notes

No hurry on adding a draft release notes while this pull request is still in draft and under active revision. I'll leave a first little comment now just to give a starting place for when the pull request is ready to get into the documentation phase. Thanks!

Some (probably all obvious) items and questions that might be relevant to cover in the eventual release note:

  • By chance, for the initial release, will users have the option of switching back to the previous fast deployment approach with a deprecation warning?

  • Relatedly, will users control fast deployment the same way as in the previous implementation? For example, will the $(AndroidFastDeploymentType) property still be used, and will the Assemblies and Dexes options be the same?

  • From glancing at the corresponding pieces in monodroid, I think there might be some Android OS version requirements that the release note can mention.

  • And then of course, a little comparison of the exciting user-facing timing performance and other feature benefits of the new implementation will be good to include!

jonpryor pushed a commit that referenced this pull request May 21, 2020
#4643)

Changes: xamarin/monodroid@5849ea1...e795bce

  * xamarin/monodroid@e795bcef3: Bump to xamarin/androidtools@739afe5 (#1095)
  * xamarin/monodroid@97451721c: [tools/msbuild] add $(_AndroidAllowDeltaInstall) (#1089)

Add ***Experimental*** "`.apk` delta installation" support.

*What do we want?!*  Faster `.apk` installs!  (See also PR #4690.)

The question, as ever, is *how* to reduce the time of `.apk` installs,
and what the tradeoffs are.  Fast dev, which removes assemblies from
the `.apk`, is one way to do that; PR #4690 is "fastdev v2", which does
more there.

But for everything else in the `.apk` -- Android Assets, Resources, and
more -- how do we make deploying it faster?

Here is one way.

Android Studio contains an [`installer`][0] utility, built for each
supported Android target platform, which is installed onto the target
device as `/data/local/tmp/.studio/bin/installer`.  `installer` works
in terms of "protocol buffers", and can *in place update* an `.apk`
file installed on the Android target via a "delta" between the
currently installed `.apk` and the "to be installed" `.apk`.
`installer` deals with *just* `.apk` contents, and thus doesn't
special-case Android Assets, Resources, or IL assemblies.

As the `installer` utility is Apache 2 licensed, Xamarin.Android can
redistribute and use the `installer` utility as well.

To use `installer` to deploy `.apk` updates:

 1. Use a Xamarin.Android install which contains `installer`
    integration, e.g. via `make make prepare-external-git-dependencies`
    or via a master AzDO-hosted build.

 2. Install an app:

        msbuild /t:Install samples/HelloWorld/HelloWorld.csproj

 3. Make a change, e.g. by editing
    `samples/HelloWorld/Resources/layout/Main.axml`.

 4. Install the app, enabling use of this new feature:

         msbuild /t:Install samples/HelloWorld/HelloWorld.csproj /p:_AndroidAllowDeltaInstall=True 

     This triggers the following in the code:

     a. Create the `.apk` to deploy, "as normal".

     b. Check to see if `installer` is present on the Android target.
        If not, deploy to `/data/local/tmp/.studio/bin/installer`.         
        This happens optimistically, by trying to start up
	`installer`, looking for certain error codes that indicate the
	installer isn't present, then installing `installer` if needed.

     c. Invoke the target's `installer` to obtain the contents of the
        *currently installed* `.apk` file.

     d. Compute a diff between (4.c) and the `.apk` in (4.a).

     e. Deploy the diff to the Android target.

     f. Invoke `installer` to apply the diff (4.e) to the installed
        `.apk`, updating its contents to that of (4.a).

     g. If this process fails for any reason, a "normal" `adb install`
        is performed.

This new workflow is only performed when:

  * The `$(_AndroidAllowDeltaInstall)` MSBuild Property is True
  * The App is *already deployed* to the Android target.
  * The Android target is running API-24 (Android v7.0) or later.

Some initial Install timing results for step (4), against a Pixel 3a.
Timings are total times, including the build, of which the deploy part
takes on the order of 1.5 - 2.5 sec or so:

| Test                                          |    Normal (s) |     Delta (s) |
|:----------------------------------------------|--------------:|--------------:|
| 18MB APK, fast deploy off, updated 1 assembly |           6.3 |           5.6 |
| 9MB APK, fast deploy on, updated 1 resource   |           5.6 |           5.3 |

[0]: https://android.googlesource.com/platform/tools/base/+/studio-master-dev/deploy/installer
@dellis1972 dellis1972 force-pushed the fastdevv2 branch 2 times, most recently from 15eb283 to 9138c92 Compare May 26, 2020 13:04
jonpryor pushed a commit that referenced this pull request May 26, 2020
#4643)

Changes: https://github.com/xamarin/monodroid/compare/52312f241428fc78f4d15baaa80b56f85a180427...8d51d0af0572db1583a8ab5ec095bec3046ae476

  * xamarin/monodroid@8d51d0af0: Bump to xamarin/androidtools/d16-7@767cfdfe (#1095)
  * xamarin/monodroid@a0fcae82e: [tools/msbuild] add $(_AndroidAllowDeltaInstall) (#1089)
  * xamarin/monodroid@781e564e5: [tests] Fix build from xamarin-android (#1093)

Add ***Experimental*** "`.apk` delta installation" support.

*What do we want?!*  Faster `.apk` installs!  (See also PR #4690.)

The question, as ever, is *how* to reduce the time of `.apk` installs,
and what the tradeoffs are.  Fast dev, which removes assemblies from
the `.apk`, is one way to do that; PR #4690 is "fastdev v2", which does
more there.

But for everything else in the `.apk` -- Android Assets, Resources, and
more -- how do we make deploying it faster?

Here is one way.

Android Studio contains an [`installer`][0] utility, built for each
supported Android target platform, which is installed onto the target
device as `/data/local/tmp/.studio/bin/installer`.  `installer` works
in terms of "protocol buffers", and can *in place update* an `.apk`
file installed on the Android target via a "delta" between the
currently installed `.apk` and the "to be installed" `.apk`.
`installer` deals with *just* `.apk` contents, and thus doesn't
special-case Android Assets, Resources, or IL assemblies.

As the `installer` utility is Apache 2 licensed, Xamarin.Android can
redistribute and use the `installer` utility as well.

To use `installer` to deploy `.apk` updates:

 1. Use a Xamarin.Android install which contains `installer`
    integration, e.g. via `make make prepare-external-git-dependencies`
    or via a master AzDO-hosted build.

 2. Install an app:

        msbuild /t:Install samples/HelloWorld/HelloWorld.csproj

 3. Make a change, e.g. by editing
    `samples/HelloWorld/Resources/layout/Main.axml`.

 4. Install the app, enabling use of this new feature:

         msbuild /t:Install samples/HelloWorld/HelloWorld.csproj /p:_AndroidAllowDeltaInstall=True

     This triggers the following in the code:

     a. Create the `.apk` to deploy, "as normal".

     b. Check to see if `installer` is present on the Android target.
        If not, deploy to `/data/local/tmp/.studio/bin/installer`.
        This happens optimistically, by trying to start up
	`installer`, looking for certain error codes that indicate the
	installer isn't present, then installing `installer` if needed.

     c. Invoke the target's `installer` to obtain the contents of the
        *currently installed* `.apk` file.

     d. Compute a diff between (4.c) and the `.apk` in (4.a).

     e. Deploy the diff to the Android target.

     f. Invoke `installer` to apply the diff (4.e) to the installed
        `.apk`, updating its contents to that of (4.a).

     g. If this process fails for any reason, a "normal" `adb install`
        is performed.

This new workflow is only performed when:

  * The `$(_AndroidAllowDeltaInstall)` MSBuild Property is True
  * The App is *already deployed* to the Android target.
  * The Android target is running API-24 (Android v7.0) or later.

Some initial Install timing results for step (4), against a Pixel 3a.
Timings are total times, including the build, of which the deploy part
takes on the order of 1.5 - 2.5 sec or so:

| Test                                          |    Normal (s) |     Delta (s) |
|:----------------------------------------------|--------------:|--------------:|
| 18MB APK, fast deploy off, updated 1 assembly |           6.3 |           5.6 |
| 9MB APK, fast deploy on, updated 1 resource   |           5.6 |           5.3 |

[0]: https://android.googlesource.com/platform/tools/base/+/studio-master-dev/deploy/installer
@dellis1972 dellis1972 force-pushed the fastdevv2 branch 11 times, most recently from a8925ce to b205cc8 Compare June 9, 2020 09:18
@dellis1972 dellis1972 force-pushed the fastdevv2 branch 8 times, most recently from ea24767 to f2f133e Compare June 15, 2020 13:47
@dellis1972 dellis1972 force-pushed the fastdevv2 branch 4 times, most recently from 8a47abe to a96c11f Compare June 24, 2020 11:19
@dellis1972 dellis1972 force-pushed the fastdevv2 branch 6 times, most recently from adfd244 to 1a382ee Compare October 9, 2020 09:12
@dellis1972 dellis1972 changed the title Fast Deployment Version Next [WIP] [Xamarin.Android.Build.Tasks] Fast Deployment v2.0 Oct 9, 2020
@dellis1972 dellis1972 force-pushed the fastdevv2 branch 3 times, most recently from d2d0179 to 4b6fd6b Compare October 12, 2020 16:48
@jonpryor
Copy link
Contributor

Squash-and-merge commit message:

Fixes: https://github.com/xamarin/xamarin-android/issues/4996
Fixes: https://github.com/xamarin/xamarin-android/issues/5009
Fixes: https://github.com/xamarin/xamarin-android/issues/5147

Changes: https://github.com/xamarin/monodroid/compare/1ac5333ec5e90b4e1fb9b324714811effdede37f...767f647151936303c294d154d0d0a4da8b601464

  * xamarin/monodroid@767f64715: [msbuild] Fast Deployment v2.0 (#1090)
  * xamarin/monodroid@0f04ba56d: Merge pull request #1115 from xamarin/remove-xreitem
  * xamarin/monodroid@d75341fc3: Remove provisionator file completely
  * xamarin/monodroid@b62e8c693: Replace XreItem with supported Xcode and JavaJDK syntax

The Fast Deployment system used for debugging Xamarin.Android apps has
been completely re-written.  This is mostly due to changes in Android
which means we can no longer use the external storage directory to
store assemblies.

Fast Deployment works by not including files which change often,
like assemblies, in the actual apk.  This means the `.apk` will mostly
not need to be re-installed during a debugging/development session.
Instead the assemblies are "Fast Deployed" to a special directory where
a debug version of our runtime knows where to find them.

Historically this was on the external storage directory such as

	/storage/emulated/0/Android/data/com.some.package
	/mnt/shell/emulated/0/Android/data/com.some.package
	/storage/sdcard/Android/data/com.some.package

With Android 11, these directories are no longer accessible.  Instead,
we need to deploy the assemblies into the app's internal `files`
directory.  This is usually located in `/data/data/@PACKAGE_NAME@`.
This is not a global writable folder, so we need to use the `run-as`
tool to run all the commands to copy the files into that directory.

The `run-as` tool does not always work on older devices.  From this
point on Fast Deployment v2 will only be available on API-21+ devices.
If a certain device does not support the `run-as` tool, then you can
always fall back to debugging without Fast Deployment.  While this is
slower, it should still work on most devices.

[`$(AndroidFastDeploymentType)`][0] is still supported.  This will
deploy both assemblies, native libraries, typemaps, and `.dex` files to
the `files` directory.  Support for Fast Deploying Android resources
and assets was removed in commit f0d565fe, as it required the use of
deprecated API's to work.

The Shared Runtime has also be removed in this new system.  Previously,
we used to deploy the BCL and API specific assemblies via separate
`.apk` files.  This new system removes the need for that.  All the BCL
and API specific assemblies will be deployed to the `files` directory
like all the other assemblies.

The new system is on par with the existing system when it comes to
speed.  More improvements are planned in future releases which should
make it much quicker.

Using the `samples\HelloWorld` project these are the performance
differences using `HelloWorld.csproj /restore /t:Install /v:n`:

  * Deploy "from Clean"
    * v1: 00:00:11.42
    * v2: 00:00:11.78 [3% longer]
  * Incrementally deploy C#-based change
    * v1: 00:00:02.58
    * v2: 00:00:02.43 [6% faster]

[0]: https://docs.microsoft.com/en-us/xamarin/android/deploy-test/building-apps/build-properties#androidfastdeploymenttype

Fixes dotnet#5009
Fixes dotnet#5147
Fixes dotnet#4996

The Fast Deployment system used for debugging Xamarin.Android
apps has been completely re-written. This is mostly due to
changes in the android OS which means we can no longer use
the external storage directory to store assemblies.

Fast Deployment works by not including files which change often,
like assemblies, in the actual apk. This means the .apk will
mostly not need to be re-installed during a debugging/development
session. Instead the assemblies are "Fast Deployed" to a special
directory where a debug version of our runtime knows where to find
them.

Historically this was on the external storage directory such as

    `/storage/emulated/0/Android/data/com.some.package`
    `/mnt/shell/emulated/0/Android/data/com.some.package`
    `/storage/sdcard/Android/data/com.some.package`

With the advent of Android 11, these directories are no longer accessable.
So instead we need to deploy the assemblies into the app internal `files`
directory. This is usually located in `/data/data/com.some.package`. This
is not a global writable folder, so we need to use the `run-as` tool to
run all the commands to copy the files into that diectory.

The `run-as` tool does not always work on older devices. So from this point on
Fast Deployment will only be available on API 21 devices or newer. If a certain
device does not support the `run-as` tool, then you can always fall back to
debugging without Fast Deployment. While this is slower, it should still work
on most devices.

The [Enhanced Fast Deployment](~/android/deploy-test/building-apps/build-properties.md#AndroidFastDeploymentType) mode is still available with this new system.
This will deploy both assemblies, native libraries, typemaps and dexes to the `files`
directory. Support for Fast Deploying resources and assets via that system was
removed in commit [f0d565f](dotnet@f0d565f). This was becuase it required the use of
depreicated API's to work.

The Shared Runtime has also be removed in this new system. Before we used to deploy
the BCL and API specific assemblies via seperate .apks. This new system removes
the need for that. All the BCL and API specific assemblies will be deployed to the
`files` directory like all the other assemblies.

The new system is on par with the existing system when it comes to speed. More
improvements are planned in future releases which should make it much quicker.

Using the `samples\HelloWorld` project these are the performance differences
using `HelloWorld.csproj /restore /t:Install /v:n`

Old From Clean Time Elapsed 00:00:11.42
Old C# Change Time Elapsed 00:00:02.58

New From Clean Time Elapsed 00:00:11.78
New C# Change Time Elapsed 00:00:02.43
@jonpryor jonpryor merged commit 71dc718 into dotnet:master Oct 12, 2020
@dellis1972 dellis1972 deleted the fastdevv2 branch October 13, 2020 08:11
@MagicAndre1981
Copy link

I always disabled FastDeployment because I use ADB over Wifi most time and had issues in the past. Does this v2 fix it? Does it work fine with the buildin wireless debugging of Android 11? @dellis1972

@dellis1972
Copy link
Contributor Author

@MagicAndre1981 I'm not sure I can test it and see though :)

@dellis1972
Copy link
Contributor Author

@MagicAndre1981 the new fast dev system doesn't change how the debugger attaches, which seems to be the actual problem with #3018. So the new system should still be able to deploy over wifi, the question is if the debugger can attach. Its possible there might have been fix in the adb port forwarding over wifi that might make it work in the latest sdk versions.

@MagicAndre1981
Copy link

ok, when will this change be part of VS2019? 16.9? @dellis1972

@dellis1972
Copy link
Contributor Author

@MagicAndre1981 it will be in 16.9 unless something really bad happens (like it breaks everyone :P).

I just tested out Debugging Unit tests on a Wifi connected device (Android 11) with this new system and it all seems to work without any issues :) Those tests don't run inside VS2019 though so it might still be an issue from VS. But they do use the mono SoftDebugger which is what VS uses so it might work.

I seem to remember you use custom ROMs, so it will depend on what changes you made to the ROM images.

@MagicAndre1981
Copy link

I only used custom ROM in past for an older phone, now the Pixel3a supports it officially with Android11. So I'll try it with 16.9 @dellis1972. Hopefully until 16.9, my blocker issue gets also fixed because XF5 will require VS2019 and I have to ditch my VS2017 VM

@brendanzagaeski brendanzagaeski added bug Component does not function as intended. enhancement Proposed change to current functionality. labels Nov 10, 2020
pjcollins added a commit to pjcollins/android that referenced this pull request Jan 6, 2021
Context: dotnet#4690

As of Fast Deployment v2.0 we are no longer using the Shared Runtime
packages to fast deploy certain files.  It should be safe to remove
these from our installers at this time.
@github-actions github-actions bot locked and limited conversation to collaborators Jan 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Component does not function as intended. enhancement Proposed change to current functionality.
Projects
None yet
5 participants