public void GenerateCode(Interface type)
        {
            w.WriteLine ("\tpublic interface " + type.Name + " : global::Android.OS.IInterface");
            w.WriteLine ("\t{");
            foreach (var m in type.Methods)
                GenerateCode (m);
            w.WriteLine ("\t}");

            w.WriteLine (@"
            public abstract class {0}Stub : global::Android.OS.Binder, global::Android.OS.IInterface, {1}{2}{0}
            {{
            const string descriptor = ""{3}{2}{4}"";
            public {0}Stub ()
            {{
            this.AttachInterface (this, descriptor);
            }}

            public static {1}{2}{0} AsInterface (global::Android.OS.IBinder obj)
            {{
            if (obj == null)
                return null;
            var iin = (global::Android.OS.IInterface) obj.QueryLocalInterface (descriptor);
            if (iin != null && iin is {1}{2}{0})
                return ({1}{2}{0}) iin;
            return new Proxy (obj);
            }}

            public global::Android.OS.IBinder AsBinder ()
            {{
            return this;
            }}

            protected override bool OnTransact (int code, global::Android.OS.Parcel data, global::Android.OS.Parcel reply, int flags)
            {{
            switch (code) {{
            case global::Android.OS.BinderConsts.InterfaceTransaction:
                reply.WriteString (descriptor);
                return true;",
            // end of long formatted output...
                type.Name,
                self_ns,
                unit.Package != null ? "." : String.Empty,
                unit.Package != null ? unit.Package.ToJavaString () : null,
                type.JavaName);

            foreach (var method in type.Methods) {
                bool isVoidReturn = method.ReturnType.ToString () == "void";
                w.WriteLine (@"
            case Transaction{0}: {{
                data.EnforceInterface (descriptor);", method.Name);
                for (int i = 0; method.Arguments != null && i < method.Arguments.Length; i++) {
                    var a = method.Arguments [i];
                    w.WriteLine ("\t\t\t\t{0} {1} = default ({0});", ToOutputTypeName (name_cache.ToCSharp (a.Type)), "arg" + i);
                    if (a.Modifier == null || a.Modifier.Contains ("in"))
                        w.WriteLine ("\t\t\t\t{0}", GetCreateStatements (a.Type, "data", "arg" + i));
                }
                string args = String.Join (", ", (from i in Enumerable.Range (0, method.Arguments.Length) select "arg" + i).ToArray ());
                if (isVoidReturn)
                    w.WriteLine ("\t\t\t\tthis.{0} ({1});", method.Name, args);
                else
                    w.WriteLine ("\t\t\t\tvar result = this.{0} ({1});", method.Name, args);
                if (method.Modifier == null || !method.Modifier.Contains ("oneway"))
                    w.WriteLine ("\t\t\t\treply.WriteNoException ();");
                if (!isVoidReturn)
                    w.WriteLine ("\t\t\t\t{0}", GetWriteStatements (method.ReturnType, "reply", "result", "global::Android.OS.ParcelableWriteFlags.ReturnValue"));
                for (int i = 0; method.Arguments != null && i < method.Arguments.Length; i++) {
                    var a = method.Arguments [i];
                    if (a.Modifier == null || a.Modifier.Contains ("out"))
                        w.WriteLine ("\t\t\t\t{0}", GetWriteStatements (a.Type, "data", "arg" + i, "global::Android.OS.ParcelableWriteFlags.None"));
                }
                w.WriteLine ("\t\t\t\treturn true;");
                w.WriteLine ("\t\t\t\t}");
            }
            w.WriteLine (@"
            }}
            return base.OnTransact (code, data, reply, flags);
            }}

            public class Proxy : Java.Lang.Object, {1}{2}{0}
            {{
            global::Android.OS.IBinder remote;

            public Proxy (global::Android.OS.IBinder remote)
            {{
                this.remote = remote;
            }}

            public global::Android.OS.IBinder AsBinder ()
            {{
                return remote;
            }}

            public string GetInterfaceDescriptor ()
            {{
                return descriptor;
            }}",
                type.Name, self_ns, unit.Package != null ? "." : String.Empty);
            foreach (var method in type.Methods) {
                string args = JoinArguments (method);
                w.WriteLine (@"
            public {0} {1} ({2})
            {{
                global::Android.OS.Parcel __data = global::Android.OS.Parcel.Obtain ();
            ", ToOutputTypeName (name_cache.ToCSharp (method.ReturnType)), method.Name, args);
                bool isOneWay = type.Modifier == "oneway";
                bool hasReturn = method.ReturnType.ToString () != "void";
                if (!isOneWay)
                    w.WriteLine ("\t\t\t\tglobal::Android.OS.Parcel __reply = global::Android.OS.Parcel.Obtain ();");
                if (hasReturn)
                    w.WriteLine ("{0} __result = default ({0});", ToOutputTypeName (name_cache.ToCSharp (method.ReturnType)));
                w.WriteLine (@"
                try {
                    __data.WriteInterfaceToken (descriptor);");
                foreach (var arg in method.Arguments)
                    if (arg.Modifier == null || arg.Modifier.Contains ("in"))
                        w.WriteLine ("\t\t\t\t\t" + GetWriteStatements (arg.Type, "__data", SafeCSharpName (arg.Name), "global::Android.OS.ParcelableWriteFlags.None"));
                w.WriteLine ("\t\t\t\t\tremote.Transact ({1}Stub.Transaction{0}, __data, {2}, 0);",
                    method.Name,
                    type.Name,
                    isOneWay ? "null" : "__reply");
                if (!isOneWay)
                    w.WriteLine ("\t\t\t\t\t__reply.ReadException ();");
                if (hasReturn)
                    w.WriteLine ("\t\t\t\t\t{0}", GetCreateStatements (method.ReturnType, "__reply", "__result"));
                foreach (var arg in method.Arguments)
                    if (arg.Modifier != null && arg.Modifier.Contains ("out"))
                        w.WriteLine ("\t\t\t\t\t{0}", GetReadStatements (arg.Type, "__reply", SafeCSharpName (arg.Name)));
                if (hasReturn)
                    w.WriteLine (@"
                } finally {
                    __reply.Recycle ();
                    __data.Recycle ();
                }
                return __result;");
                else
                    w.WriteLine (@"
                } finally {
                    __data.Recycle ();
                }");
                w.WriteLine (@"
            }
            ");
            }
            w.WriteLine (@"
            }"); // end of Proxy

            for (int i = 0; i < type.Methods.Length; i++) {
                var method = type.Methods [i];
                w.WriteLine (@"
            internal const int Transaction{0} = global::Android.OS.Binder.InterfaceConsts.FirstCallTransaction + {1};", method.Name, i);
            }
            foreach (var method in type.Methods)
                w.WriteLine (@"
            public abstract {0} {1} ({2});",
                    ToOutputTypeName (name_cache.ToCSharp (method.ReturnType)),
                    method.Name,
                    JoinArguments (method));
            w.WriteLine (@"
            }"); // end of Stub
        }
        public void GenerateCode(Interface type)
        {
            w.WriteLine("\tpublic interface " + type.Name + " : global::Android.OS.IInterface");
            w.WriteLine("\t{");
            foreach (var m in type.Methods)
            {
                GenerateCode(m);
            }
            w.WriteLine("\t}");

            w.WriteLine(@"
	public abstract class {0}Stub : global::Android.OS.Binder, global::Android.OS.IInterface, {1}{2}{0}
	{{
		const string descriptor = ""{3}{2}{4}"";
		public {0}Stub ()
		{{
			this.AttachInterface (this, descriptor);
		}}

		public static {1}{2}{0} AsInterface (global::Android.OS.IBinder obj)
		{{
			if (obj == null)
				return null;
			var iin = (global::Android.OS.IInterface) obj.QueryLocalInterface (descriptor);
			if (iin != null && iin is {1}{2}{0})
				return ({1}{2}{0}) iin;
			return new Proxy (obj);
		}}

		public global::Android.OS.IBinder AsBinder ()
		{{
			return this;
		}}

		protected override bool OnTransact (int code, global::Android.OS.Parcel data, global::Android.OS.Parcel reply, int flags)
		{{
			switch (code) {{
			case global::Android.OS.BinderConsts.InterfaceTransaction:
				reply.WriteString (descriptor);
				return true;"                ,
// end of long formatted output...
                        type.Name,
                        self_ns,
                        unit.Package != null ? "." : String.Empty,
                        unit.Package != null ? unit.Package.ToJavaString() : null,
                        type.JavaName);

            foreach (var method in type.Methods)
            {
                cl_variable = null;
                bool isVoidReturn = method.ReturnType.ToString() == "void";
                w.WriteLine(@"
			case Transaction{0}: {{
				data.EnforceInterface (descriptor);"                , method.Name);
                for (int i = 0; method.Arguments != null && i < method.Arguments.Length; i++)
                {
                    var a = method.Arguments [i];
                    w.WriteLine("\t\t\t\t{0} {1} = default ({0});", ToOutputTypeName(name_cache.ToCSharp(a.Type)), "arg" + i);
                    if (a.Modifier == null || a.Modifier.Contains("in"))
                    {
                        w.WriteLine("\t\t\t\t{0}", GetCreateStatements(a.Type, "data", "arg" + i));
                    }
                }
                string args = String.Join(", ", (from i in Enumerable.Range(0, method.Arguments.Length) select "arg" + i).ToArray());
                if (isVoidReturn)
                {
                    w.WriteLine("\t\t\t\tthis.{0} ({1});", method.Name, args);
                }
                else
                {
                    w.WriteLine("\t\t\t\tvar result = this.{0} ({1});", method.Name, args);
                }
                if (method.Modifier == null || !method.Modifier.Contains("oneway"))
                {
                    w.WriteLine("\t\t\t\treply.WriteNoException ();");
                }
                if (!isVoidReturn)
                {
                    w.WriteLine("\t\t\t\t{0}", GetWriteStatements(method.ReturnType, "reply", "result", "global::Android.OS.ParcelableWriteFlags.ReturnValue"));
                }
                for (int i = 0; method.Arguments != null && i < method.Arguments.Length; i++)
                {
                    var a = method.Arguments [i];
                    if (a.Modifier == null || a.Modifier.Contains("out"))
                    {
                        w.WriteLine("\t\t\t\t{0}", GetWriteStatements(a.Type, "data", "arg" + i, "global::Android.OS.ParcelableWriteFlags.None"));
                    }
                }
                w.WriteLine("\t\t\t\treturn true;");
                w.WriteLine("\t\t\t\t}");
            }
            w.WriteLine(@"
			}}
			return base.OnTransact (code, data, reply, flags);
		}}

		public class Proxy : Java.Lang.Object, {1}{2}{0}
		{{
			global::Android.OS.IBinder remote;

			public Proxy (global::Android.OS.IBinder remote)
			{{
				this.remote = remote;
			}}

			public global::Android.OS.IBinder AsBinder ()
			{{
				return remote;
			}}

			public string GetInterfaceDescriptor ()
			{{
				return descriptor;
			}}"            ,
                        type.Name, self_ns, unit.Package != null ? "." : String.Empty);
            foreach (var method in type.Methods)
            {
                cl_variable = null;
                string args = JoinArguments(method);
                w.WriteLine(@"
			public {0} {1} ({2})
			{{
				global::Android.OS.Parcel __data = global::Android.OS.Parcel.Obtain ();
", ToOutputTypeName(name_cache.ToCSharp(method.ReturnType)), method.Name, args);
                bool isOneWay  = type.Modifier == "oneway";
                bool hasReturn = method.ReturnType.ToString() != "void";
                if (!isOneWay)
                {
                    w.WriteLine("\t\t\t\tglobal::Android.OS.Parcel __reply = global::Android.OS.Parcel.Obtain ();");
                }
                if (hasReturn)
                {
                    w.WriteLine("{0} __result = default ({0});", ToOutputTypeName(name_cache.ToCSharp(method.ReturnType)));
                }
                w.WriteLine(@"
				try {
					__data.WriteInterfaceToken (descriptor);"                    );
                foreach (var arg in method.Arguments)
                {
                    if (arg.Modifier == null || arg.Modifier.Contains("in"))
                    {
                        w.WriteLine("\t\t\t\t\t" + GetWriteStatements(arg.Type, "__data", SafeCSharpName(arg.Name), "global::Android.OS.ParcelableWriteFlags.None"));
                    }
                }
                w.WriteLine("\t\t\t\t\tremote.Transact ({1}Stub.Transaction{0}, __data, {2}, 0);",
                            method.Name,
                            type.Name,
                            isOneWay ? "null" : "__reply");
                if (!isOneWay)
                {
                    w.WriteLine("\t\t\t\t\t__reply.ReadException ();");
                }
                if (hasReturn)
                {
                    w.WriteLine("\t\t\t\t\t{0}", GetCreateStatements(method.ReturnType, "__reply", "__result"));
                }
                foreach (var arg in method.Arguments)
                {
                    if (arg.Modifier != null && arg.Modifier.Contains("out"))
                    {
                        w.WriteLine("\t\t\t\t\t{0}", GetReadStatements(arg.Type, "__reply", SafeCSharpName(arg.Name)));
                    }
                }
                if (hasReturn)
                {
                    w.WriteLine(@"
				} finally {
					__reply.Recycle ();
					__data.Recycle ();
				}
				return __result;"                );
                }
                else
                {
                    w.WriteLine(@"
				} finally {
					__data.Recycle ();
				}"                );
                }
                w.WriteLine(@"
			}
");
            }
            w.WriteLine(@"
		}"        ); // end of Proxy

            for (int i = 0; i < type.Methods.Length; i++)
            {
                var method = type.Methods [i];
                w.WriteLine(@"
		internal const int Transaction{0} = global::Android.OS.Binder.InterfaceConsts.FirstCallTransaction + {1};"        , method.Name, i);
            }
            foreach (var method in type.Methods)
            {
                w.WriteLine(@"
		public abstract {0} {1} ({2});"        ,
                            ToOutputTypeName(name_cache.ToCSharp(method.ReturnType)),
                            method.Name,
                            JoinArguments(method));
            }
            w.WriteLine(@"
	}"    ); // end of Stub
        }