1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "generate_java.h"
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "Type.h"
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <string.h>
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdio.h>
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdlib.h>
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <string.h>
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass StubClass : public Class
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    StubClass(Type* type, Type* interfaceType);
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~StubClass();
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* transact_code;
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* transact_data;
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* transact_reply;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* transact_flags;
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    SwitchStatement* transact_switch;
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiprivate:
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    void make_as_interface(Type* interfaceType);
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiStubClass::StubClass(Type* type, Type* interfaceType)
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :Class()
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->comment = "/** Local-side IPC implementation stub class. */";
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->modifiers = PUBLIC | ABSTRACT | STATIC;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->what = Class::CLASS;
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->type = type;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->extends = BINDER_NATIVE_TYPE;
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->interfaces.push_back(interfaceType);
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // descriptor
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Field* descriptor = new Field(STATIC | FINAL | PRIVATE,
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            new Variable(STRING_TYPE, "DESCRIPTOR"));
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    descriptor->value = "\"" + interfaceType->QualifiedName() + "\"";
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(descriptor);
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ctor
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* ctor = new Method;
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->modifiers = PUBLIC;
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->comment = "/** Construct the stub at attach it to the "
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        "interface. */";
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->name = "Stub";
46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->statements = new StatementBlock;
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MethodCall* attach = new MethodCall(THIS_VALUE, "attachInterface",
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            2, THIS_VALUE, new LiteralExpression("DESCRIPTOR"));
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(attach);
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(ctor);
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // asInterface
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    make_as_interface(interfaceType);
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // asBinder
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* asBinder = new Method;
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->modifiers = PUBLIC | OVERRIDE;
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->returnType = IBINDER_TYPE;
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->name = "asBinder";
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->statements = new StatementBlock;
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    asBinder->statements->Add(new ReturnStatement(THIS_VALUE));
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(asBinder);
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // onTransact
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->transact_code = new Variable(INT_TYPE, "code");
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->transact_data = new Variable(PARCEL_TYPE, "data");
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->transact_reply = new Variable(PARCEL_TYPE, "reply");
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->transact_flags = new Variable(INT_TYPE, "flags");
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* onTransact = new Method;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->modifiers = PUBLIC | OVERRIDE;
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->returnType = BOOLEAN_TYPE;
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->name = "onTransact";
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->parameters.push_back(this->transact_code);
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->parameters.push_back(this->transact_data);
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->parameters.push_back(this->transact_reply);
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->parameters.push_back(this->transact_flags);
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->statements = new StatementBlock;
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        onTransact->exceptions.push_back(REMOTE_EXCEPTION_TYPE);
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(onTransact);
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->transact_switch = new SwitchStatement(this->transact_code);
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    onTransact->statements->Add(this->transact_switch);
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MethodCall* superCall = new MethodCall(SUPER_VALUE, "onTransact", 4,
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    this->transact_code, this->transact_data,
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    this->transact_reply, this->transact_flags);
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    onTransact->statements->Add(new ReturnStatement(superCall));
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiStubClass::~StubClass()
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiStubClass::make_as_interface(Type *interfaceType)
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* obj = new Variable(IBINDER_TYPE, "obj");
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* m = new Method;
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->comment = "/**\n * Cast an IBinder object into an ";
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->comment += interfaceType->QualifiedName();
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->comment += " interface,\n";
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->comment += " * generating a proxy if needed.\n */";
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->modifiers = PUBLIC | STATIC;
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->returnType = interfaceType;
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->name = "asInterface";
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->parameters.push_back(obj);
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        m->statements = new StatementBlock;
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* ifstatement = new IfStatement();
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ifstatement->statements = new StatementBlock;
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    m->statements->Add(ifstatement);
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IInterfaceType* iinType = new IInterfaceType();
119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable *iin = new Variable(iinType, "iin");
120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface, NULL);
121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    m->statements->Add(iinVd);
122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Ensure the instance type of the local object is as expected.
124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // One scenario where this is needed is if another package (with a
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // different class loader) runs in the same process as the service.
126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) iin;
128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Comparison* instOfCheck = new Comparison(iin, " instanceof ",
130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            new LiteralExpression(interfaceType->QualifiedName()));
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* instOfStatement = new IfStatement();
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        instOfStatement->statements = new StatementBlock;
134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        instOfStatement->statements->Add(new ReturnStatement(new Cast(interfaceType, iin)));
135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    m->statements->Add(instOfStatement);
136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    string proxyType = interfaceType->QualifiedName();
138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyType += ".Stub.Proxy";
139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    NewExpression* ne = new NewExpression(NAMES.Find(proxyType));
140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ne->arguments.push_back(obj);
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    m->statements->Add(new ReturnStatement(ne));
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(m);
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass ProxyClass : public Class
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic:
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ProxyClass(Type* type, InterfaceType* interfaceType);
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    virtual ~ProxyClass();
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* mRemote;
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool mOneWay;
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski};
158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
159282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiProxyClass::ProxyClass(Type* type, InterfaceType* interfaceType)
160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    :Class()
161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->modifiers = PRIVATE | STATIC;
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->what = Class::CLASS;
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->type = type;
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->interfaces.push_back(interfaceType);
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mOneWay = interfaceType->OneWay();
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // IBinder mRemote
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    mRemote = new Variable(IBINDER_TYPE, "mRemote");
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(new Field(PRIVATE, mRemote));
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // Proxy()
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* remote = new Variable(IBINDER_TYPE, "remote");
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* ctor = new Method;
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->name = "Proxy";
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->statements = new StatementBlock;
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ctor->parameters.push_back(remote);
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ctor->statements->Add(new Assignment(mRemote, remote));
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(ctor);
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // IBinder asBinder()
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* asBinder = new Method;
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->modifiers = PUBLIC | OVERRIDE;
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->returnType = IBINDER_TYPE;
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->name = "asBinder";
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        asBinder->statements = new StatementBlock;
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    asBinder->statements->Add(new ReturnStatement(mRemote));
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    this->elements.push_back(asBinder);
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiProxyClass::~ProxyClass()
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// =================================================
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_new_array(Type* t, StatementBlock* addTo, Variable* v,
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Variable* parcel)
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* len = new Variable(INT_TYPE, v->name + "_length");
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    IfStatement* lencheck = new IfStatement();
204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    lencheck->statements->Add(new Assignment(v, NULL_VALUE));
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    lencheck->elseif = new IfStatement();
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    lencheck->elseif->statements->Add(new Assignment(v,
208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                new NewArrayExpression(t, len)));
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    addTo->Add(lencheck);
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_write_to_parcel(Type* t, StatementBlock* addTo, Variable* v,
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Variable* parcel, int flags)
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 0) {
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->WriteToParcel(addTo, v, parcel, flags);
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 1) {
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->WriteArrayToParcel(addTo, v, parcel, flags);
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_create_from_parcel(Type* t, StatementBlock* addTo, Variable* v,
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Variable* parcel, Variable** cl)
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 0) {
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->CreateFromParcel(addTo, v, parcel, cl);
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 1) {
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->CreateArrayFromParcel(addTo, v, parcel, cl);
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_read_from_parcel(Type* t, StatementBlock* addTo, Variable* v,
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            Variable* parcel, Variable** cl)
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 0) {
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->ReadFromParcel(addTo, v, parcel, cl);
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (v->dimension == 1) {
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        t->ReadArrayFromParcel(addTo, v, parcel, cl);
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_method(const method_type* method, Class* interface,
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    StubClass* stubClass, ProxyClass* proxyClass, int index)
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg_type* arg;
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int i;
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    bool hasOutParams = false;
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    const bool oneway = proxyClass->mOneWay || method->oneway;
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the TRANSACT_ constant =============================================
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    string transactCodeName = "TRANSACTION_";
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    transactCodeName += method->name.data;
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    char transactCodeValue[60];
264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Field* transactCode = new Field(STATIC | FINAL,
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            new Variable(INT_TYPE, transactCodeName));
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    transactCode->value = transactCodeValue;
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    stubClass->elements.push_back(transactCode);
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the declaration in the interface ===================================
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* decl = new Method;
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->comment = gather_comments(method->comments_token->extra);
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->modifiers = PUBLIC;
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->returnType = NAMES.Search(method->type.type.data);
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->returnTypeDimension = method->type.dimension;
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->name = method->name.data;
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        decl->parameters.push_back(new Variable(
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            NAMES.Search(arg->type.type.data), arg->name.data,
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            arg->type.dimension));
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    decl->exceptions.push_back(REMOTE_EXCEPTION_TYPE);
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    interface->elements.push_back(decl);
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the stub method ====================================================
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Case* c = new Case(transactCodeName);
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data);
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // interface token validation is the very first thing we do
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    c->statements->Add(new MethodCall(stubClass->transact_data,
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            "enforceInterface", 1, new LiteralExpression("DESCRIPTOR")));
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // args
302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* cl = NULL;
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    VariableFactory stubArgs("_arg");
304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type* t = NAMES.Search(arg->type.type.data);
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* v = stubArgs.Get(t);
308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        v->dimension = arg->type.dimension;
309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c->statements->Add(new VariableDeclaration(v));
311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (convert_direction(arg->direction.data) & IN_PARAMETER) {
313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_create_from_parcel(t, c->statements, v,
314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    stubClass->transact_data, &cl);
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (arg->type.dimension == 0) {
317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                c->statements->Add(new Assignment(v, new NewExpression(v->type)));
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            else if (arg->type.dimension == 1) {
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                generate_new_array(v->type, c->statements, v,
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        stubClass->transact_data);
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            else {
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        __LINE__);
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        realCall->arguments.push_back(v);
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the real call
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _result = NULL;
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (0 == strcmp(method->type.type.data, "void")) {
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c->statements->Add(realCall);
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!oneway) {
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // report that there were no exceptions
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            MethodCall* ex = new MethodCall(stubClass->transact_reply,
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "writeNoException", 0);
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c->statements->Add(ex);
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    } else {
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        _result = new Variable(decl->returnType, "_result",
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                decl->returnTypeDimension);
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        c->statements->Add(new VariableDeclaration(_result, realCall));
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (!oneway) {
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // report that there were no exceptions
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            MethodCall* ex = new MethodCall(stubClass->transact_reply,
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "writeNoException", 0);
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            c->statements->Add(ex);
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // marshall the return value
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        generate_write_to_parcel(decl->returnType, c->statements, _result,
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    stubClass->transact_reply,
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    Type::PARCELABLE_WRITE_RETURN_VALUE);
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // out parameters
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    i = 0;
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type* t = NAMES.Search(arg->type.type.data);
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* v = stubArgs.Get(i++);
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_write_to_parcel(t, c->statements, v,
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                stubClass->transact_reply,
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                Type::PARCELABLE_WRITE_RETURN_VALUE);
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            hasOutParams = true;
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // return true
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    c->statements->Add(new ReturnStatement(TRUE_VALUE));
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    stubClass->transact_switch->cases.push_back(c);
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // == the proxy method ===================================================
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* proxy = new Method;
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->comment = gather_comments(method->comments_token->extra);
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->modifiers = PUBLIC | OVERRIDE;
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->returnType = NAMES.Search(method->type.type.data);
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->returnTypeDimension = method->type.dimension;
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->name = method->name.data;
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->statements = new StatementBlock;
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = method->args;
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (arg != NULL) {
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            proxy->parameters.push_back(new Variable(
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            NAMES.Search(arg->type.type.data), arg->name.data,
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            arg->type.dimension));
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            arg = arg->next;
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->exceptions.push_back(REMOTE_EXCEPTION_TYPE);
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxyClass->elements.push_back(proxy);
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the parcels
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _data = new Variable(PARCEL_TYPE, "_data");
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxy->statements->Add(new VariableDeclaration(_data,
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                new MethodCall(PARCEL_TYPE, "obtain")));
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Variable* _reply = NULL;
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (!oneway) {
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        _reply = new Variable(PARCEL_TYPE, "_reply");
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->statements->Add(new VariableDeclaration(_reply,
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                    new MethodCall(PARCEL_TYPE, "obtain")));
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the return value
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    _result = NULL;
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (0 != strcmp(method->type.type.data, "void")) {
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        _result = new Variable(proxy->returnType, "_result",
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                method->type.dimension);
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->statements->Add(new VariableDeclaration(_result));
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // try and finally
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    TryStatement* tryStatement = new TryStatement();
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxy->statements->Add(tryStatement);
424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    FinallyStatement* finallyStatement = new FinallyStatement();
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxy->statements->Add(finallyStatement);
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the interface identifier token: the DESCRIPTOR constant, marshalled as a string
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken",
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            1, new LiteralExpression("DESCRIPTOR")));
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the parameters
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    arg = method->args;
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (arg != NULL) {
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Type* t = NAMES.Search(arg->type.type.data);
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int dir = convert_direction(arg->direction.data);
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (dir == OUT_PARAMETER && arg->type.dimension != 0) {
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            IfStatement* checklen = new IfStatement();
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            checklen->expression = new Comparison(v, "==", NULL_VALUE);
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            checklen->statements->Add(new MethodCall(_data, "writeInt", 1,
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        new LiteralExpression("-1")));
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            checklen->elseif = new IfStatement();
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            checklen->elseif->statements->Add(new MethodCall(_data, "writeInt",
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        1, new FieldVariable(v, "length")));
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            tryStatement->statements->Add(checklen);
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        else if (dir & IN_PARAMETER) {
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_write_to_parcel(t, tryStatement->statements, v, _data, 0);
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = arg->next;
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the transact call
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4,
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            new LiteralExpression("Stub." + transactCodeName),
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            _data, _reply ? _reply : NULL_VALUE,
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                            new LiteralExpression(
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0"));
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    tryStatement->statements->Add(call);
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // throw back exceptions.
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (_reply) {
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        MethodCall* ex = new MethodCall(_reply, "readException", 0);
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        tryStatement->statements->Add(ex);
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // returning and cleanup
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (_reply != NULL) {
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (_result != NULL) {
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_create_from_parcel(proxy->returnType,
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    tryStatement->statements, _result, _reply, &cl);
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the out/inout parameters
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        arg = method->args;
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        while (arg != NULL) {
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Type* t = NAMES.Search(arg->type.type.data);
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                generate_read_from_parcel(t, tryStatement->statements,
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                                            v, _reply, &cl);
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            arg = arg->next;
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    if (_result != NULL) {
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        proxy->statements->Add(new ReturnStatement(_result));
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_interface_descriptors(StubClass* stub, ProxyClass* proxy)
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the interface descriptor transaction handler
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Case* c = new Case("INTERFACE_TRANSACTION");
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    c->statements->Add(new MethodCall(stub->transact_reply, "writeString",
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            1, new LiteralExpression("DESCRIPTOR")));
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    c->statements->Add(new ReturnStatement(TRUE_VALUE));
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    stub->transact_switch->cases.push_back(c);
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // and the proxy-side method returning the descriptor directly
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Method* getDesc = new Method;
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    getDesc->modifiers = PUBLIC;
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    getDesc->returnType = STRING_TYPE;
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    getDesc->returnTypeDimension = 0;
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    getDesc->name = "getInterfaceDescriptor";
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    getDesc->statements = new StatementBlock;
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    getDesc->statements->Add(new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    proxy->elements.push_back(getDesc);
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiClass*
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskigenerate_binder_interface_class(const interface_type* iface)
518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    InterfaceType* interfaceType = static_cast<InterfaceType*>(
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NAMES.Find(iface->package, iface->name.data));
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the interface class
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    Class* interface = new Class;
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        interface->comment = gather_comments(iface->comments_token->extra);
525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        interface->modifiers = PUBLIC;
526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        interface->what = Class::INTERFACE;
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        interface->type = interfaceType;
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        interface->interfaces.push_back(IINTERFACE_TYPE);
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the stub inner class
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    StubClass* stub = new StubClass(
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NAMES.Find(iface->package, append(iface->name.data, ".Stub").c_str()),
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        interfaceType);
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    interface->elements.push_back(stub);
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // the proxy inner class
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    ProxyClass* proxy = new ProxyClass(
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        NAMES.Find(iface->package,
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                         append(iface->name.data, ".Stub.Proxy").c_str()),
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        interfaceType);
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    stub->elements.push_back(proxy);
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // stub and proxy support for getInterfaceDescriptor()
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    generate_interface_descriptors(stub, proxy);
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // all the declared methods of the interface
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    int index = 0;
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    interface_item_type* item = iface->interface_items;
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    while (item != NULL) {
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (item->item_type == METHOD_TYPE) {
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            method_type * method_item = (method_type*) item;
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            generate_method(method_item, interface, stub, proxy, method_item->assigned_id);
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        item = item->next;
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        index++;
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    return interface;
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
561