-
Notifications
You must be signed in to change notification settings - Fork 533
/
PreserveApplications.cs
98 lines (78 loc) · 2.36 KB
/
PreserveApplications.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Collections;
using System.Linq;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Tuner;
using Mobile.Tuner;
using Mono.Cecil;
namespace MonoDroid.Tuner {
public class PreserveApplications : BaseMarkHandler
{
public override void Initialize (LinkContext context, MarkContext markContext)
{
base.Initialize (context, markContext);
markContext.RegisterMarkAssemblyAction (assembly => ProcessAssembly (assembly));
markContext.RegisterMarkTypeAction (type => ProcessType (type));
}
public bool IsActiveFor (AssemblyDefinition assembly)
{
return Annotations.GetAction (assembly) == AssemblyAction.Link;
}
public void ProcessAssembly (AssemblyDefinition assembly)
{
if (!IsActiveFor (assembly))
return;
ProcessAttributeProvider (assembly);
}
public void ProcessType (TypeDefinition type)
{
if (!IsActiveFor (type.Module.Assembly))
return;
if (!type.Inherits ("Android.App.Application", cache))
return;
ProcessAttributeProvider (type);
}
void ProcessAttributeProvider (ICustomAttributeProvider provider)
{
if (!provider.HasCustomAttributes)
return;
const string ApplicationAttribute = "Android.App.ApplicationAttribute";
foreach (CustomAttribute attribute in provider.CustomAttributes)
if (attribute.Constructor.DeclaringType.FullName == ApplicationAttribute)
PreserveApplicationAttribute (attribute);
}
void PreserveApplicationAttribute (CustomAttribute attribute)
{
PreserveTypeProperty (attribute, "BackupAgent");
PreserveTypeProperty (attribute, "ManageSpaceActivity");
}
void PreserveTypeProperty (CustomAttribute attribute, string property)
{
if (!attribute.HasProperties)
return;
var type_ref = (TypeReference) attribute.Properties.First (p => p.Name == property).Argument.Value;
if (type_ref == null)
return;
var type = type_ref.Resolve ();
if (type == null)
return;
PreserveDefaultConstructor (type);
}
void PreserveDefaultConstructor (TypeDefinition type)
{
if (!type.HasMethods)
return;
foreach (MethodDefinition ctor in type.Methods.Where (t => t.IsConstructor)) {
if (!ctor.IsStatic && !ctor.HasParameters) {
PreserveMethod (type, ctor);
break;
}
}
}
void PreserveMethod (TypeDefinition type, MethodDefinition method)
{
Annotations.AddPreservedMethod (type, method);
}
}
}