Skip to content

Commit 5bba16e

Browse files
jonathanpeppersjonpryor
authored andcommitted
[Xamarin.Android.Build.Tasks] add $(_AndroidAllowDeltaInstall) support (#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
1 parent 7c27644 commit 5bba16e

File tree

5 files changed

+27
-2
lines changed

5 files changed

+27
-2
lines changed

.external

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
xamarin/monodroid:d16-7@52312f241428fc78f4d15baaa80b56f85a180427
1+
xamarin/monodroid:d16-7@8d51d0af0572db1583a8ab5ec095bec3046ae476
22
mono/mono:2020-02@075c3f06197e3b969f4234d0f56a2e10ee6ee305

NuGet.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" protocolVersion="3" />
77
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
88
<add key="dotnet internal feed" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" protocolVersion="3" />
9+
10+
<!-- This is needed (currently) for the Xamarin.Android.Deploy.Installer dependency, getting the installer -->
11+
<!-- Android binary, to support delta APK install -->
12+
<add key="xamarin.android util" value="https://pkgs.dev.azure.com/xamarin/public/_packaging/Xamarin.Android/nuget/v3/index.json" />
913
</packageSources>
1014
<config>
1115
<add key="globalPackagesFolder" value="packages" />

build-tools/installers/create-installers.targets

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@
386386
<_MSBuildFiles Include="$(MSBuildSrcDir)\Xamarin.Android.Build.Debugging.Tasks.pdb" />
387387
<_MSBuildFiles Include="$(MSBuildSrcDir)\Xamarin.Android.Common.Debugging.props" />
388388
<_MSBuildFiles Include="$(MSBuildSrcDir)\Xamarin.Android.Common.Debugging.targets" />
389+
<_MSBuildFiles Include="$(MSBuildSrcDir)\lib\arm64-v8a\installer" />
390+
<_MSBuildFiles Include="$(MSBuildSrcDir)\lib\armeabi-v7a\installer" />
391+
<_MSBuildFiles Include="$(MSBuildSrcDir)\lib\x86\installer" />
392+
<_MSBuildFiles Include="$(MSBuildSrcDir)\lib\x86_64\installer" />
393+
<_MSBuildFiles Include="$(MSBuildSrcDir)\protobuf-net.dll" />
394+
<_MSBuildFiles Include="$(MSBuildSrcDir)\System.Collections.Immutable.dll" />
389395
<_MSBuildFiles Include="$(MSBuildSrcDir)\Xamarin.Android.Tools.ResourceProcessors.dll" />
390396
<_MSBuildFiles Include="$(MSBuildSrcDir)\Xamarin.AndroidTools.dll" />
391397
<_MSBuildFiles Include="$(MSBuildSrcDir)\Xamarin.AndroidTools.pdb" />

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public static class KnownProperties
3131
public const string IntermediateOutputPath = "IntermediateOutputPath";
3232
public const string AndroidFastDeploymentType = "AndroidFastDeploymentType";
3333
public const string AndroidClassParser = "AndroidClassParser";
34+
public const string _AndroidAllowDeltaInstall = "_AndroidAllowDeltaInstall";
3435
}
3536
}
3637

tests/MSBuildDeviceIntegration/Tests/DebuggingTest.cs

100644100755
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,39 +276,51 @@ public override void OnCreate ()
276276
/* useSharedRuntime */ false,
277277
/* embedAssemblies */ true,
278278
/* fastDevType */ "Assemblies",
279+
/* allowDeltaInstall */ false,
279280
},
280281
new object[] {
281282
/* useSharedRuntime */ false,
282283
/* embedAssemblies */ false,
283284
/* fastDevType */ "Assemblies",
285+
/* allowDeltaInstall */ false,
284286
},
285287
new object[] {
286288
/* useSharedRuntime */ true,
287289
/* embedAssemblies */ true,
288290
/* fastDevType */ "Assemblies",
291+
/* allowDeltaInstall */ false,
289292
},
290293
new object[] {
291294
/* useSharedRuntime */ true,
292295
/* embedAssemblies */ false,
293296
/* fastDevType */ "Assemblies",
297+
/* allowDeltaInstall */ false,
294298
},
295299
new object[] {
296300
/* useSharedRuntime */ true,
297301
/* embedAssemblies */ true,
298302
/* fastDevType */ "Assemblies:Dexes",
303+
/* allowDeltaInstall */ false,
299304
},
300305
new object[] {
301306
/* useSharedRuntime */ true,
302307
/* embedAssemblies */ false,
303308
/* fastDevType */ "Assemblies:Dexes",
309+
/* allowDeltaInstall */ false,
310+
},
311+
new object[] {
312+
/* useSharedRuntime */ true,
313+
/* embedAssemblies */ false,
314+
/* fastDevType */ "Assemblies",
315+
/* allowDeltaInstall */ true,
304316
},
305317
};
306318
#pragma warning restore 414
307319

308320
[Test]
309321
[TestCaseSource (nameof(DebuggerTestCases))]
310322
[Retry (1)]
311-
public void ApplicationRunsWithDebuggerAndBreaks (bool useSharedRuntime, bool embedAssemblies, string fastDevType)
323+
public void ApplicationRunsWithDebuggerAndBreaks (bool useSharedRuntime, bool embedAssemblies, string fastDevType, bool allowDeltaInstall)
312324
{
313325
if (!CommercialBuildAvailable) {
314326
Assert.Ignore ("Test does not run on the Open Source Builds.");
@@ -326,6 +338,8 @@ public void ApplicationRunsWithDebuggerAndBreaks (bool useSharedRuntime, bool em
326338
};
327339
var abis = new string [] { "armeabi-v7a", "x86" };
328340
proj.SetProperty (KnownProperties.AndroidSupportedAbis, string.Join (";", abis));
341+
if (allowDeltaInstall)
342+
proj.SetProperty (KnownProperties._AndroidAllowDeltaInstall, "true");
329343
proj.SetDefaultTargetDevice ();
330344
using (var b = CreateApkBuilder (Path.Combine ("temp", TestName))) {
331345
SetTargetFrameworkAndManifest (proj, b);

0 commit comments

Comments
 (0)