"In/out/inout" in a AIDL interface parameter value? - android

I'm programming a radio streaming app. I run the "radio playing" as a remote Service by using AIDL interface technique to communicate with the Service. But I don't really understand one thing.
What is the "out" in a AIDL interface parameter value?
Like this:
String doSomething(in String a, out String[] b);
I understand "in", that is sending data to the remote when the method is called from activity.
What is the "out", and why we need "in" and "out" in same method? In which case are they("out/inout") used? Why is the String[] "out"?
Please help..

In AIDL, the out tag specifies an output-only parameter. In other words, it's a parameter that contains no interesting data on input, but will be filled with data during the method.
For example, a method that copies an array of bytes might be specified like this:
void copyArray(in byte[] source, out byte[] dest);
The inout tag indicates that the parameter has meaning on both input and output. For example:
void charsToUpper(inout char[] chars);
This is important because the contents of every parameter must be marshalled (serialized, transmitted, received, and deserialized). The in/out tags allow the Binder to skip the marshalling step for better performance.

Here it goes,
Its only a directional tag indicating which way the data goes.
in - object is transferred from client to service only used for
inputs
out - object is transferred from client to service only used
for outputs.
inout - object is transferred from client to service
used for both inputs and outputs.
All non-primitive parameters require a directional tag indicating which way the data goes. Either in, out, or inout.
Primitives are in by default, and cannot be otherwise
Please note, RPC calls from clients are synchronous.
You should limit the direction to what is truly needed, because marshaling parameters is expensive.
Example:
Please check the below AIDL interface to understand it in a better way.
package com.hardian.sample.aidl;
import com.hardian.sample.aidl.TeamMember;
interface ITeamManageService {
void getTeamCaptian(out TeamMember member);
void updateTeamMember(inout TeamMember member, in boolean isLeader);
oneway void removeTeamMember(in TeamMember member);
}
Here we have used out, in, inout directional tags to indicate which way the data goes.
getTeamCaptian(out TeamMember member) :
Get the captain of the team.
Here the "out" directional tag means, when the client calls this method, the "member" object has no relevant data,
but the server shall make changes to the "member" object, so the client shall get the updated "member" object.
In fact, the method call is synchronous.
updateTeamMember(inout TeamMember member, in boolean isLeader) :
Update the captian of the team.
Here the "inout" directional tag means, when the client calls this method,the "member" object has relevant data in it.
And the server shall use the input data and process it. Once the process completed, the client shall get the relevant data back.
In fact, the method call is synchronous.
removeTeamMember(in TeamMember member)
Remove a member from the team.
Here the "in" directional tag means, the "member" object is transferred from client to service only used for inputs.
If any changes are made to the "member" object in the service then it won’t reflect in the client.
The method call is asynchronous, we can put the "oneway" keyword to the method signature.
Asynchronous methods must not have "out" and "inout" arguments, they must also return void.

Related

What is the correct way to share Active Objects between processes?

I am looking into sharing active objects between two processes, however the documentation regarding it is often lackluster and sometimes even incorrect.
Specifically I was looking into sharing a Binder objects via parcels. The documentation states.
Active Objects
An unusual feature of Parcel is the ability to read and write active objects. For these objects the actual contents of the object is not written, rather a special token referencing the object is written. When reading the object back from the Parcel, you do not get a new instance of the object, but rather a handle that operates on the exact same object that was originally written. There are two forms of active objects available.
Binder objects are a core facility of Android's general cross-process communication system. The IBinder interface describes an abstract protocol with a Binder object. Any such interface can be written in to a Parcel, and upon reading you will receive either the original object implementing that interface or a special proxy implementation that communicates calls back to the original object. The methods to use are writeStrongBinder(IBinder), writeStrongInterface(IInterface), readStrongBinder(), writeBinderArray(IBinder[]), readBinderArray(IBinder[]), createBinderArray(), writeBinderList(List), readBinderList(List), createBinderArrayList().
However when receiving the parcel, the object returned is merely a BinderProxy, which cannot be cast to the original class or implement any calls beyond basic IBinder calls. While this is obviously the proxy object referred to in the documentation, I was wondering what the method was for referencing the original object that was alluded to in the same statement.
I was also wondering if there was a source where this topic was more thoroughly explained or documented.
You should be able to cast the objects to its original class, given that it implement the Parcelable interface correctly. Casting it's just like this:
// in ProcessDataActivity retrieve User
Intent intent = getIntent();
ParcelableObjectExample usr = (ParcelableObjectExample)
intent.getParcelableExtra("parcelableExample");
For this to be successful you need to correctly implement the Parcelable interface on ParcelableObjectExample, for this you must:
Implement its describeContents method
Implement its abstract method writeToParcel, which takes the current state of the object and writes it to a Parcel
Add a static field called CREATOR to our class, which is an object implementing the Parcelable.Creator interface
Add a Constructor that takes a Parcel as parameter. The CREATOR calls that constructor to rebuild our object.

Parceling objects in android to transfer from one activity to another

Recently an interviewer asked me a very tricky question.
There are several parts of the question.
Why (question is why and not how) do you need to parcel objects while sending from one activity to another and not send directly
Answer I gave -
Parcelable gives the capability to developers to restrict object
creation which in a way makes it faster to use.
I was confused on the part, so decided to site difference between using serializable and parcelable :p (clever huuuhhh !),
http://www.developerphil.com/parcelable-vs-serializable/ used this reference.
While using Bundle, when we use String, int we do not need to parcel the data, so do you think the String/int is by default internally parcelled ?
Answer I gave -
because String/int is a primitive data-type, if we had used the
Wrapper class directly, might be possible we had to use parcelable(I
am not sure on that part)
I did not get any useful link after googling, also I or the interviewer is not quite satisfied with the answer.
If you guys can help, would be wonderful !
Why (question is why and not how) do you need to parcel objects while sending from one activity to another and not send directly
Parcelling/serializing objects isn't for speed as you had guessed.
When you're sending data between Activities, and especially between different applications (remember that Intent objects aren't only meant for communication between your own Activities, but are also for between yours and those of other apps as well), you cannot expect the sender and the receiver to have access to the same memory address spaces.
Android's documentation states that applications run in their own discrete memory spaces. Here's a quote to that effect from the docs:
Each process has its own virtual machine (VM), so an app's code runs in isolation from other apps.
So when you want to send an object myObject to some receiving Activity, you can't send its reference/pointer because the receiver won't necessarily have access to the location specified by the pointer. Instead you'll have to send some representation of myObject that the receiver can access and use -- this is why you need to marshall the data into a form that can be unmarshalled, and the easiest way to do so is to simply have the class of the object implement Serializable which lets Java do its best to convert the object into an array of bytes that can be easily sent to and unmarshalled by the receiver. But since Serializable uses reflection, this is slow.
You can use other ways that are faster to marshall the data -- one, for example, is converting the object into its JSON representation using a library like Gson and just sending it across since any JSON document can be represented as a String and easily converted back to a Java Object. Another way, which is probably faster in pretty much all cases is using the Parcelable interface which lets you specify exactly how you want to marshall the data and exactly how it should be unmarshalled. It basically gives you more control on the transmission of the object.
The tl:dr: Parcelling/Serializing etc is used because you can't send memory addresses across, so you have to send the actual data of the object and it has to be represented in some form.
While using Bundle, when we use String, int we do not need to parcel the data, so do you think the String/int is by default internally parcelled ?
How Bundle works internally is that it puts everything into a Map and parcels/unparcels the data as needed (ie when get/put is called). For putting Objects into a Bundle, the object's class needs to implement Serializable or Parcelable because it needs to tell the Bundle how it should be marshalled/unmarshalled internally.
But primitive types and Strings are simple enough and used often enough that the developer doesn't need to specify how that needs to happen and Bundle provides convenience methods for it. I can't give you a solid answer at the lowest level of how they works because a lot of the Parcel code is natively implemented and I couldn't find it online, but they must certainly be straightforward to convert to their representation in bytes.
Just to add what #uj- said, Parcelling/Serializing is needed as #uj- said it will be sent across JVMs so they need to be converted into some format so that the other party will be able to understand.
Let me take an example to explain why serializing/parcelling is needed,
you are sending data from an application written in "C++" to an application written in java, so the following are the classes,
In C++,
class Android {
public: int dataToSend; //for example purpose making field public and omitting setter/getters
}
In Java,
class Android{
public int dataToSend;
}
suppose the C++ code generates dynamic library (which will be generated by compiling using the standard C++ compiler and then linked), and Java code generates a jar (by compiling using the javac).
When the C++ application sends data (object of Android class) to the java application the way it is compiled and linked in C++ is completely different as compared to the way its compiled in java and hence java will be wondering what has this C++ application sent to me.
Hence to get rid of such problems serialisation/parcelling is needed which will make sure that both of the application know how the data is converting while transmitting through network (in case of android how it is transmitted to another activity, may be in same or different application).
And yea when we start comparing Serialisation and Parcelling, Parcelling gets the upper hand as we will be specifying the way the data must be converted when sending the data, else in the case of serialisation the object is converted to string using reflection and reflection always takes time. Hence Parcelling is faster compared to Serialisation.
For your second question,
if we consider the above example itself then we can say that String and int being primitive types (no user defined fields in them) and hence android will be able to handle the marshalling and unmarshalling of the data which will be sent.
I tried going through the code when we go on digging deeper we end up getting native code as said by #uj-.
Some extract from the android source code:
while writing the parcel:
parcel.writeInt(BUNDLE_MAGIC);
int startPos = parcel.dataPosition();
parcel.writeArrayMapInternal(mMap);
int endPos = parcel.dataPosition();
parcel.setDataPosition(lengthPos);
int length = endPos - startPos;
parcel.writeInt(length);
parcel.setDataPosition(endPos);
while reading the parcel,
int magic = parcel.readInt();
if (magic != BUNDLE_MAGIC) {
//noinspection ThrowableInstanceNeverThrown
throw new IllegalStateException("Bad magic number for Bundle: 0x"
+ Integer.toHexString(magic));
}
int offset = parcel.dataPosition();
parcel.setDataPosition(offset + length);
Parcel p = Parcel.obtain();
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
p.setDataPosition(0);
mParcelledData = p;
set the magic number which will identify the start of the parcel while writing and the same will be used while we read the parcel.
Hope I answered your question.

inout String acceptable in AIDL

The documentation states that
all non-primitive parameters require a directional tag indicating which way the data goes; and
primitives are in by default, and cannot be otherwise.
Then they proceed with giving an example where a String is missing the directional tag. Can a String be out or inout in Android AIDL?
Since strings are immutable I'd have to do an assignment on the method handling the call in order to change the string, something like myString = "hello to you too";. I know that in a regular method this argument myString would remain unchanged at the caller side. Is that behavior applied here?

How to transmit an Android Object over a Socket?

I would like to transmit an Android Object over a Socket with low overhead.
Should I use standard java.io.Serializable or android.os.Parcel?
Thank you!
Neither.
Parcel is designed for IPC, and other uses are albeit arguably efficient, dangerous. The documentation says
Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.
This also means that you need to be sure that the remote side has got the exact same version of Android and of your code to be sure it will work.
Serializable has similar problems, and in the (android) dcumentation there is even a hint towards the solution:
Warning: this interface limits how its implementing classes can change in the future. By implementing Serializable you expose your flexible in-memory implementation details as a rigid binary representation. Simple code changes--like renaming private fields--are not safe when the changed class is serializable.
[...]
Recommended Alternatives: JSON is concise, human-readable and efficient. Android includes both a streaming API and a tree API to read and write JSON. Use a binding library like GSON to read and write Java objects directly.
If you want to move data from one device to another, I think you are better off creating a protocol for the data, ship it over, and populate the remote objects with that data. JSON is probably a good place to start.
Good luck!
If your message is longer, more complex or otherwise you need more efficiency, I would recommend to try use Google Protocol Buffers. They would allow some reasonable amount of alterations like adding new fields, or removing previously optional fields, or adding a completely new structure as a field. However you will also have the real classes with the real setters and getters (can be immutable versions or mutable builders, how do you prefer). Stricter control over that do you put is not as bad thing as may appear.
think XML, but smaller, faster, and simpler
The major drawback of serialized objects is not that you cannot alter the protocol details later. Differently, you can do many compatible changes if you introduce versions numbers and you cannot rename the property name in JSON either if you want legacy client to find that property.
However serialized objects are Java specific and you cannot have a more efficient C++ server client or use Python for prototyping, for instance, if you decide in the future. Protocol buffers are language neutral.
Transmitting an object through a socket depends a lot on what will be receiving the object. Usually such a transfer relies on a text-based serialisation such as XML or JSON.
First, define an object to send. As an example, we can define a class called Message to encapsulate our communications:
public class Message implements Serializable {
private static final long serialVersionUID = 1L; // Your version number
private int senderID;
private String messageText;
public Message(int id, String text) {
senderID = id;
messageText = text;
}
public String getText() {
return messageText;
}
}
Next, instantiate the object, wrap the socket's streams in object streams, then send the message across the socket:
Message sayhey = new Message("123456789", "Hello");
Socket socket = new Socket(host, port);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(sayhey);
On the other side of the socket, the message can be retrieved and used by invoking methods on the returned object:
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Message messageObject = (Message) in.readObject();
String messageText = messageObject.getText();
you can implement Serializable.

AIDL inout param

I wanted to know what is the inout param in the AIDL is for?
I know what is in for and what out is for. (out does not marshal the object passing).
But I don't understand what is the inout for.
I have looked in the:
"In/out/inout" in a AIDL interface parameter value?
question but still did not understand.
From my testings the param is passed much like specifying it as in.
So if any1 can shed some light on what is inout It would be helpful.
Thanks
An in parameter is only transported from the caller to the callee. An out parameter is transported from the callee to the caller. And an inout parameter is transported both ways.
You would use an inout paramter when you pass an object to the callee and the callee changes it.
Here it my version of explaining the directional tags in AIDL,
Its only a directional tag indicating which way the data goes.
in - object is transferred from client to service only used for
inputs
out - object is transferred from client to service only used
for outputs.
inout - object is transferred from client to service
used for both inputs and outputs.
All non-primitive parameters require a directional tag indicating which way the data goes. Either in, out, or inout.
Primitives are in by default, and cannot be otherwise
Please note, RPC calls from clients are synchronous.
You should limit the direction to what is truly needed, because marshaling parameters is expensive.
Example:
Please check the below AIDL interface to understand it in a better way.
package com.hardian.sample.aidl;
import com.hardian.sample.aidl.TeamMember;
interface ITeamManageService {
void getTeamCaptian(out TeamMember member);
void updateTeamMember(inout TeamMember member, in boolean isLeader);
oneway void removeTeamMember(in TeamMember member);
}
Here we have used out, in, inout directional tags to indicate which way the data goes.
getTeamCaptian(out TeamMember member) :
Get the captain of the team.
Here the "out" directional tag means, when the client calls this method, the "member" object has no relevant data,
but the server shall make changes to the "member" object, so the client shall get the updated "member" object.
In fact, the method call is synchronous.
updateTeamMember(inout TeamMember member, in boolean isLeader) :
Update the captian of the team.
Here the "inout" directional tag means, when the client calls this method,the "member" object has relevant data in it.
And the server shall use the input data and process it. Once the process completed, the client shall get the relevant data back.
In fact, the method call is synchronous.
removeTeamMember(in TeamMember member)
Remove a member from the team.
Here the "in" directional tag means, the "member" object is transferred from client to service only used for inputs.
If any changes are made to the "member" object in the service then it won’t reflect in the client.
The method call is asynchronous, we can put the "oneway" keyword to the method signature.
Asynchronous methods must not have "out" and "inout" arguments, they must also return void.

Categories

Resources