 Just so you know the slides are available as an HTML document rather than a PDF document. Add that shortener basically if you go to this URL you'll see this and then you'll be able to click on this thing called slides and I'll be screen casting this and posting it as well afterwards so if you want to avoid having to take notes you can watch the video later on. So we might as well start I think I have a minute too so let me actually turn on the screen recording. So welcome to the deep diving to Android IPC and specifically binder framework. My name is Alexander Garganta and what I'm talking about is basically a couple of things you know why IPC matters and specifically on Android and how is binder different than other forms of IPC and why is it well suited for essentially what we need on Android. You're you know hopefully you're here because you're interested in binder itself but you may also be interested in how Android works and binder is basically one of those core pieces that glues everything together. Without binder literally the entire system would fall apart. So whether it's because like I said you want to take advantage of it and build your own custom apps and or low-level system services or you just want to kind of get get a sense of how it's all put together this is what we plan on covering. My only concern is is this is a little disclaimer right up front is we only have about 50 minutes this talk when I originally put it together I was aiming for two hours so I'll have to condense quite a few things and skip over certain points and or even certain slides. I know that's sometimes frustrating to do but it's the only way I'm gonna get through it. So we're gonna talk about things like what binder is you know IPC advantages comparisons of binder to other frameworks. Binder versus other forms of IPC that you might have used if you were developing apps on Android. So with terminology how the binder communicates and how the discovery works. A little bit about AIDL the essentially the reference mapping in binder which is one of the interesting pieces of it. We'll talk a little bit about kind of how you would use binder in a real application. We'll talk about asynchronous binder and why it's important. Memory sharing and concerns about memory, binder limitations and a little bit about security. So I'm again my name is Alexander Garganta I teach Android. I work for Maracana. We focus on Android on open source training and Android is a big part of it. I also run the San Francisco Android user group as well as Java user group and involved with a bunch of other things related to Android. Android is basically what I do most of the time these days. So what is binder? Binder is basically an IPC framework. I like to call it framework because it's not just the binder as you will see later on we discuss the terminology binders a lot of things. But you can think of it as a system for basically developing quote-unquote object-oriented OS. But the idea is we're not developing the OS itself to be object-oriented which we could do but rather we want to enable an operating system to behave as an object-oriented operating system. So rather than thinking of your OS as a bunch of system calls you think of your OS as a bunch of services that have states that have behavior that you can invoke at any time. Kind of like microkernel to some degree but basically something that can be bolted on to any operating system like for example Linux. So it is essential to Android. This diagram I know it's kind of small so let me zoom in a little bit. Basically gives you an idea that you know pretty much all of the applications all in system services a lot of the essentially underlying framework infrastructure middleware as we call it all depend on Android binder especially at the binder and the driver level. In terms of binder itself it comes from open binder. It was first developed for BOS back in the day. It was never really never really lived to see the day as part of BOS because B was acquired by Palm. It was then ported to the Palm kernel for the cobalt and later on the Linux kernel and eventually was basically built into a full-fledged Palm OS and served its purpose but that didn't really last too long because as we know Palm didn't really go as they hope they did. So when HP acquired I guess later on WebOS Google acquired the end hackburn and she was one of the key members of the B on the original B team of binder and so along with her came kind of the knowledge of how to do IPC in essentially embedded environment. So what is IPC and why do we care about IPC? So basically IPC can mean a lot of things but ultimately it's used for message passing, synchronization, sharing memory, isolating certain key components of the system and of course there's also something called RPC so promoting but in Android as you will see when we talk about IPC we do not assume any sort of remoting procedure calls. It enables us to separate things that provides privilege separation, data isolation, information sharing and modularity that's kind of one of the key components of it. So when it comes to IPC as you guys know you know being this is a Linux event there's many forms of IPC you know so we could be talking about files we could be talking about signals, sockets whether we're talking about Unix or TCP sockets, pipes, semaphores, shared memory, you know message passing frameworks like for example Q's, message bus and then other forms of IPC like intents, content providers, messenger right and then there's the binder. So why binder? Why specifically? Why do we need binder? Why is it so important? So again this diagram on the right-hand side kind of gives it shows you the typical stack on Android. You guys have seen this probably many times. At the bottom we have the kernel, at the top we have the applications and then in the middle we have this middleware. Well applications tend to be written in Java and in order to take advantage of the application framework services which run in separate processes they actually consume them using IPC. So this communication from applications down to application framework services is almost 99% done using binder framework. From the application framework down into the lower layers we sometimes see the use of binder, sometimes we use Unix sockets and sometimes we directly load the drivers through you know essentially JNI and bunch of other things like hauls. But that's beyond beyond this talk. So in Android binder specifically provides us with security so one of the features of it is that it enables us to run things in separate processes and as a result of that we get better security isolation i.e. sandboxing. Stability so if things crash because they're running separate processes and because we have a good IPC framework in place you know they can be restarted without affecting other things in the system. Memory management so one of the key features of Android memory management is this ability to be able to kill off applications that are no longer needed either by activity manager service doing the job or in case it can't cope with memory demands having the low memory killer can. But for that to work you need to be able to cleanly shut down entire process you cannot have applications share the underlying process essentially infrastructure so you need IPC to enable that process to be able to exist and be able to still coexist you know with other processes in the system. And then like I said even even basically Android's own components and apps all run in separate processes so specifically what does what does binder essentially do for us. It replaces all forms of IPC or I should say system 5 traditional system 5 based IPC on Android so there's no support on Android so for Sys5, semaphores, shared segments, message queues and whatnot. One of the main reasons for that is because Android's you know essentially ability to kill out the processes without ever having any sort of cleanup action scheduled means that if you were to use traditional IPC it may not work very well because you may essentially end up with a visor leakage and you may have malicious code essentially you know contribute to denial of service attacks. Binder has a built-in IP reference counting mechanism which enables it to count objects if you will that are shared across process boundaries and when they're no longer needed because say the process that was sharing them dies those objects can be automatically essentially well the users of those objects can be notified and those references can be automatically reclaimed without having any sort of lingering resources be left in the system. This is very key to essentially why Android binder survives essentially this hostile environment with low memory killer where other IPC frameworks don't. One of the other features of binder compared to other forms of IPC is the so-called thread migration programming model so the idea is with binder is you as the client of the binder framework you basically make an invocation a method invocation on an object that to you appears to be local but in reality that object lives somewhere else and what will happen is that your thread will by default block and on the other side will continue running if you will that method invocation code of course it's no longer your thread it's somebody else's thread but what's interesting is that to you it appears like your thread just jumped on into another process and started executing within the you know those process boundary so that's really key because it enables very easy programming model to exist on Android we also have features like for example identifying senders of requests this is actually very key to Android security being able to know who's talking to whom at any time enables us to enforce permissions dynamically and this is how most Android services do it we also have unique object mapping across boundaries process boundaries so basically if I share a service object a binder object with another process and that process shares that same object with that yet another process that reference that object is unique across all processes on the system and the kernel driver ensures of that and this actually key to how the discovery of bound services works on Android as we will talk about in a moment we also have ability to send file descriptors across also process boundaries so for example if you want to play a media file in a media server you're not sending the entire file over you're sending just merely the file descriptors that file to the other process underneath the hood the file descriptors descriptors get the duped and basically copy it over to the other side. Android also comes away with something called AIDL which is basically interface definition language that allows services to describe their capabilities to clients and moreover Android comes with a tool called the AIDL that can extract proxies and stubs which do automatic marshaling and un-martialing of data as we will talk about in a moment. All of that you get for free of course only if you do it in Java but nevertheless the idea is you get you as a consumer of the binder framework have actually very little to do to take advantage of it. You have a fairly simplified transaction model sorry I skipped one very simple support for marshaling and a marshaling of common data types although custom types are also supported again this other generation of stubs and proxies is important. The recursion across process boundaries is built in so if a process A calls process B and process B calls back into process A that works out of the box and if your process A happens to be talking to a binder object which is actually also inside a process A so it's not IPC anymore it's local you are essentially skipping the entire overhead of marshaling and invoking things locally. It is not meant for RPC it is very much oriented towards essentially client service or message passing it's not necessarily well suited for streaming and it's not the part of any sort of standard so binder is not part of POSIX or anything like that so there's you know it's API and implementation are one and the same. As we will see pretty much everything you do in Android depends on binder drawing on the screen depends on binder handling touch events depends on binder you know playing stuff you know handling callbacks to your application depends on binder you know you send the game tense receiving intense and whatnot that all depends on binder so it's extremely important. Now that said a lot of Android low-level system services also take advantage of the UNIX domain sockets as a form of communication so binder is not the only game in town but it's the most common one. So a lot of things when I talk about binder people ask well why why don't I need to know about binder why don't I just use intense and content providers and certainly you can. I'm not going to go into too much depth but the idea is that in Android if you have two applications they want to talk to each other they can literally just half for example their activities open up each other via intents. The activity that has been invoked can respond back with some results to the caller via another intent. You can also start services with intents you can send intents as broadcast messages you can receive them and whatnot. That also is IPC. This down below which I'm going to kind of skip is an example of how you could do that and many of you who have ever written Android applications have probably done something like this but basically you can have an application create an intent start another application with that intent that intent contains think of it as the parameters of that request the other application can get that intent handle the get the data out of that intent do some work on the behalf of the caller create another intent and basically send the result and then the calling application gets the result and processes that. It works and it's well suited it's very there's actually low coupling because these intents are not are well-defined the data parameters are well-defined but the problem is that this is all not really very OOP it's asynchronous it's not very well suited for situations where you want you know low latency and at the end of the day all of this still underneath the hood uses binder so yes intents are a form of communication between applications and there's nothing wrong with that especially if you're just creating simple trivial things but if you want much more essentially you know up to the millisecond notifications between or communication between multiple apps and you don't want to depend on the asynchronous nature of intents well then you may want to go that to that bottom level and take a look at binder another thing that comes up a lot is messenger IPC now messenger I don't know how many of you know is basically a mechanism that allows a remote process to use a messenger to call back to a local handler thereby passing you messages so basically the idea is let's say you had an application it's probably best understood if I just you know explain the code briefly let's say you have an application that wants to have some other service they'll do downloads of a bunch of images or something what it could do is you create an intent to put a bunch of URIs that it wants downloaded and they then a messenger into that intent and send it over to the service that service on the other hand we can get that intent get the URIs from the from the intent and start acting on those URIs for example say initiated downloads but it say wants to notify the original application when every URI or every URL or I guess resource gets downloaded what it could do is you can get create a message and then essentially stick that message into the messenger send it to via the messenger to the other side the other side essentially pass the messenger which was you know linked to a local handler that handler will just get a call back on to this handle message it will receive the message and then act on it so that is a form of IPC it's well more much more it's much better you know to do it that this way than to use frequent essentially intense and sending bunch of intense because that actually is not even an option so if this particular use case it's it's pretty good but on you know underneath the hood there's still uses bind there it's still a synchronous and it's still not the most well you know the as well suited for low latency because you still have to go through go through these handlers which are essentially message cues. So before we talk about binder how binder works I just want to kind of briefly mention a few things about binders is a terminology because binder means a lot of things so first of all there's a binder as a framework which is essentially the overall IPC architecture it's not just the driver there's lip binder there's these proxies and stops and whatnot a lot of these things essentially come into play when we when we talk about binder so at the very low level like at the very bottom right here we have the binder driver so that is what facilitates the actual communication or exchange of messages across process boundaries. Yes I know this is a Linux conference this is what we're mostly interested in but then again this alone would be useless had it not been for the rest of the front in the infrastructure. The protocol so the protocol is just how we communicate with the binder driver and most of the time we're essentially sending it eye octals. The eye binder interface is essentially a simple interface that defines the basic mechanisms of every binder object. Binder objects are those things that we actually want to use those are the things that represent the services we want to interact with so as you will as you will see later on these eye binder objects have capabilities like for example telling us whether they're alive or we can go and subscribe to be notified when they die so this is expressed using the default eye binder interface. AIDL is I mentioned a language that enables us to define business operations that go on top of the eye binder interface and essentially that's what you know is what what our clients are after without the you know the business operations was the point of using generic eye binder objects. The actual binder object that is a basic implementation of that eye binder interface it provides a very basic infrastructure and that's what we end up extending from when it comes time to build building our own actual binder services. Binder tokens are basically think of them as handles or think of them as pointers but they happen to be agnostic to the process they're in so essentially a binder object can be referenced by a token or a handle that is unique across an entire operating system so essentially it's a reference that ends up being unique and can be passed around. Binder service that's what we are actually consuming that's what we're interacting with so for example location you know a service is is a binder service or activity manager service or power manager service vibrator service you know surface flinger sensor service and so on and so on these are all services that essentially implement binder. Binder client that's what we use to essentially interact with the service. The binder transaction that's essentially exchange of if you will data between the client and service through the binder driver and the transactions are as you will see fairly simple they involve just copying data back and forth a lot of a lot of what happens then is handled by the framework. The binder parcel is basically a unit of data that essentially gets sent across process boundaries so when we send the message to the remote service we're actually sending it in form of a parcel so marshaling is a mechanism of converting our rich data types i.e. a request that contains for example objects or data types that mean have meaning to us into a parcel on marshaling is the reverse of that taking a parcel that was received through a binder driver essentially and on marshaling converting it back into rich and say Java or C++ or even C data types into something that we can work with. Proxies and stubs are the things that get auto-generated and essentially are the things that enable automatic marshaling and un-marshaling if you are if you happen to be coding things in Java in which case they are truly auto-generated if you happen to be coding them in C++ then you have to go and write your own proxies and stubs and finally the context manager that is the thing that enables discovery of binder services because you know having this remote process somewhere with these binder services available in it is useless unless we get a reference to them to begin with and in Android that context manager is called service manager and that's a daemon that most of you have probably seen if you've done PS so let's take a look at kind of how this communication works so at the end you know what we ultimately want as the users of binder is to have a client talking to a service they just happen to be in different processes that's kind of what we are after but in reality we cannot just go into another process in essentially voc operations another process because that would violate the process isolation so we have to go through something that has ability to interact with both processes and that's the kernel so that's where the binder driver comes into play so how it typically works is that a service that wants to basically be consumed by clients will come to the driver and register by essentially spawning off threads that will block on the binder driver in these blocking Iocl calls waiting for callbacks to do work so that happens preemptively so when a client wants to actually have service do some work on its behalf it sends a message to the binder driver the driver then finds the appropriate essentially service to service that message the one of those service threads unblocks handles the request and essentially sends the response back to the binder driver via another one of those threads that again ends up blocking once the response is sent the client to this point gets the message what's interesting is that to client this feels like an ACI sorry a very synchronous communication channel the services you will see even though he has these threads doesn't have to worry about him all of that low-level thread management or thread pulling is automatically handled by the the the I should say framework I'm not going to see the driver so how does the how does this actually happen is that most of the time what we see happening is these Iocl calls for read write calls where basically a service will go to the binder driver and say hey I have some data for you of certain size and then I have I want to get some data back of sort of up to certain size I should say you know it'll basically get initially to this the structure into which later on the the the data will be populated so basically what happens is the service god comes to the binder driver for the first time the right buffer is empty just going to sit there the the and then the service then blocks when the client comes later on and sends them request to the service the binder driver takes the request copies it into basically the buffer that the service is going to then read from and then tells how much data is in the buffer and then at that point unblocks the service now the service has some data when it produces a result it goes and basically takes the result writes it into again one of these buffers into this right buffer and basically gives goes and gives it back to the the binder driver and so essentially this happens on both the service side and the client side we're just exchanging these buffers back and forth what's in the buffers is something we'll talk about in a moment but basically it's the it are the parcels plus the handles to who we want to talk to now um there's in these buffers I guess I should also say these there's these bookkeeping commands that basically tells us like for example is the service still alive is this you know if you wanted to ping something and whatnot we'll talk again about this in a little bit I have to speed up because we're gonna run out of time um however one thing I wanted to mention is that most of the time all of this communication that I just mentioned these eye octals it's very low level we actually don't want to know anything about it as the consumers of this framework we just want to basically send messages back and forth and act on messages so that's where the proxies and stuff's coming to play so the proxies job is to basically take this very high level say Java or C++ request you know receive it and then convert it into a one of those parcels and then submit an eye octal transaction to the binder driver and block on the other hand the stop's job is to basically listen if you will to the binder driver callback and then upon receiving the callback demarshal or unmartial that parcel into something that the service can understand and then call the appropriate callback method in the service the service is coded so that it only knows about these high level method calls for example you know to do something that involves rich job objects it doesn't know anything about the infrastructure except for the fact that the service has to extend from this binder object and implement this binder interface the rest of the implementation of the service is in no way you know tied to binder framework it doesn't care about it the only other thing the semantical thing that affects it is threading because every time a service gets called the invocation of the service method can happen in any one of these threads that was basically preemptively you know over here tied to the binder driver so except for the multi-threaded behavior and the fact that you have to extend for a particular class the rest of the the infrastructure is completely seamless now one more thing i want to mention before we actually two more things before we move off of this slide one is to clients i you guys you guys you know let's say you guys as application developers not as system integrators even this is way too much knowledge for you you guys as the application developers don't even want to know anything about binder about proxies about stocks you just want to basically consume some service so what andrew does for example for system services let's say locations manager service activity manager service power manager service and you name it there's like 60 of them plus what they do is they provide these so-called managers so these things a manager's job is basically to be a proxy to a proxy if you will so manager facilitates the discovery of the service you want to talk to and he hides the binder interaction away from you so for example when you're talking to a location manager you are actually talking to a local java object which underneath the hood if you were to open it up and take a look at it will convert your method calls into remote binder method calls via proxy and the reason why the manager is there is to handle certain things like you know exceptions like for example let's say you get a remoting exception if the remote thing dies as well as to handle lookup mechanisms as well as to handle some threading issues for example if you're getting asynchronous callbacks the manager's job is to take those asynchronous callbacks and convert them into something you can handle on the ui thread otherwise you have these thread you know thread issues potentially so for those of you who've done android develop application development you've been using binder all along you just haven't necessarily noticed them because you've most likely just been using your managers the last part is the discovery how do you actually find the thing you want to talk to you know to begin with well when it comes to android's built-in services basically what we need is this thing called context manager so if any of you have done you know ps on an android you know adb shell you would have seen something called service manager that is the context manager the other name point so what the context manager does very early it's actually one of those daemons that gets launched very early by in it it goes to the binder driver and says hey binder driver i want to be your context manager and the binder driver only allows one context manager at a time to be a register with it then what it does it submits essentially creates a you know a bunch of threads and waits on the binder driver it itself is a service a context manager aka service manager is a service a binder service so what is its job its job is basically to sit there and allow other services to register themselves with the context manager so for example when you have a location service the location service will be registered with the context manager as the location quote unquote location service so when a client needs to find location service all he needs to do is ask the context manager so how does that work well basically the service at some point will register with the binder driver the service will then use service manager or context manager proxy because now the service is the client to the context manager then the service this proxy is going to go to binder driver figure out where the context manager is i get a handle to the context manager and then submit a request to context manager say hey i want to register myself with you on the other side when the client wants to look up a service to talk to the client submits a request again via another one of these service manager proxies submits a request and via the request basically gets a reference to the service manager once he has a service manager he asks where's the location service for example and he gets a reference back to it and now the client can go and use it the way we talked about before so if you were to do adb shell service list you will see the list of bunch of these services so this is essentially for example the name of a service so all these services are registered by a simple string based names and then this is the you know a ideal that it implements basically or the name of the ideal that implements say for example for location but there's you know 70 plus services you will find here this diagram kind of shows you another another way of picturing all of this communication let me see if i can quickly take you through it it's somewhat redundant but i don't know if it's probably somewhat easier to grasp so let's say for example you had a service that you wanted to expose to clients how would that work and let's picture that service being part of the service manager right which is another daemon that we know exists in android so at the very beginning this is kind of starting with a negative you know this service is going to run from a main and it will basically start a pool of threads that will then go to binder so this is step minus three and essentially block they will just sit there block waiting for requests so they will issue those blocking iocl calls at that point the service will have a presumably another thread and that thread will then do a look up of the service manager which we talked about and it will then register the service with the service manager or context manager again the two names can be used interchangeably so now the client runs the client wants to use the service right how the client goes to service manager i didn't put in this diagram just because it's again it would involve a lot more errors but basically the client ultimately over here wants to invoke an operation of the service that's what he wants to do invoke some service for some method foo and for you know pass some data let's call it some bar i don't know what that is so this client will basically invoke what it what it thinks you know is a a service reference and invoke a method foo for some bar but what a client doesn't know or care this is actually what's important is that it's actually talking to a proxy not a remote object right client is actually has a reference to a local that proxy will convert their request from you know some foo that you know essentially method call foo through a transaction called foo whoops and into that transaction it will along with that transaction will basically invoke the transaction with these parcels these parcels will be auto created by the proxy and into the parcels will take the sub bar so we'll take the sub bar and it will basically shove it inside of this data parcel and then we'll invoke some transaction that transaction goes via a lib binder through a blocking iocl call to the driver over here to the binder driver the binder driver now realizes that this transaction is referencing essentially this service because the service previously registered itself with it and basically it wakes up one of those threads that was previously blocked on the binder from the service side that thread takes the parcel that was that was basically received now through the binder driver unmartials it i should say it gives it the stuff the stuff on marshals it figures out that the client wants to invoke a transaction called you know foo and it actually invokes a method on the service called foo with that same bar so that this bar you know i call it some bar basically got recreated on an in another process it went through a marshaling stage then inter-essentially copy gets copied across the process boundaries by the binder driver and then the other side gets recreated into its original state again the marshaling is built in for a lot of the common data types but you can create and roll out your own marshaling and marshaling strategies finally the service now invokes the operation the client requested which was the say the foo operation and produces some result the client or sorry i should say the service returns that result that result now goes back to the stub and via the stub gets remarshalled into now the reply parcel so it gets converted from a some result which can be say some java data type into essentially a series of bytes and then via lib binder submits gets submitted back to the binder driver right this is again the one another one of those blocking calls on the other side we unblocked because the client had been waiting all this time the proxy receives the summary that the reply parcel the proxy un-martials the reply object from the reply parcel and it gives back the reply object or some result back to the client so the same some result that got created here and returned is the very same object but now reconstructed in another process right that's roughly how things work now this is kind of a diagram i showed a couple of years ago actually or when i talked about services in android this is just the it gives you an idea of what let's say a location stack on android looks like i'm not going to go over the entire detail but just want to point out let's say you have wanted to consume a location service right what you would do is you would as a system for a system service called location what you would get is actually a location manager so what a location manager would implicitly do is do a call to the service manager which is down here to basically figure out where is the location service where's the location service location service was created created earlier on inside of the system server and got registered with the service manager via this term called location so here when the client actually says i want to say get last known coordinates what it's doing is it's talking to this but in reality this is first looking up the service and it is then going through a proxy via the binder driver into this stub and via the stub basically into service and then from the service he goes and talks to these location providers which themselves are services and they talk to howls and drivers and whatnot that's beside the point but basically the binder is key to this jumping from an application space to essentially this middleware space which itself is just another process again i wish i had more time to go over the more details but you know have to speed up so what is a ideal so a ideal basically is the language for describing the services to their clients it looks and feels like java it's not java it's similar though this is an example of an a ideal basically you know service call it some full service generally we would call this save this file into a dot a ideal file with a name that matches the name of the service you will notice that this feels like namespace because it is same like java notice we have this use of imports and now we define our interface in this interface we just define the business methods that the service is supposed to implement and not supposed to has to implement and the decline has to you know can consume these methods are just prototypes they look and feel like java so you define the return type then you define the method name and you define one or more zero or more parameters what's different is that unlike java you can also specify this essentially flag the determines which way is the data copied for example if you say in let's say you're deleting some something of type bar that means that the data is copied from the client to the service but if the service were to make some changes to bar let's say bar was immutable those changes will not be visible on the client side versus over here let's say you had this object bar do you wanted to have the service save and maybe the service updates the idea of bar when it gets saved whatever bar may be that basically you know now you know excuse me means the data gets copied both ways so what happens when you create a file like this on eclipse if you're doing this in eclipse or if using the end-of-build system will automatically employ this tool called a ideal which is part of the sdk which will generate in the gen folder this essentially ifu service which is the same as the name of the service that of the file we created which implements essentially this interface or extends this high interface and inside of it defines the stub and then the proxy the stub basically has this on-transact method that is how the service is going to receive transactions and the proxy on the other hand has the actual methods the clients are going to use and notice that what those methods do is they create these parcels convert somehow you know our data types for example this bar into a parcel so somehow they ask the bar to write itself into a parcel and then the start or sorry the proxy submits these transactions you know that yes there's more that we you know we can go much deeper than this but that's basically underneath the hood what's happening and then here's the definition of all the methods now written in java if you were to do this in c++ you end up having to basically write a lot of this code yourself so i'm not going to go into details of how that will be done right now so a ideal out of the box or binder out of the box framework supports all of these data types especially in the java land so you know all the primitives including preliminary arrays character sequences and strings of course file descriptors which i said get copied as a file descriptor um serializable objects which can get converted to bytes but java serialization is not the most optimum optimal thing in the world and should be avoided maps and lists so basically if you have you know objects that are structured into maps or lists that will be automatically marshaled and marshaled bundles which are just specialized versions of maps object arrays sparse arrays and you know sparse Boolean arrays are just more specialized and then iBinder so these are the interesting ones so anything you pass to the other side as iBinder gets passed as a reference and not as a copy so basically everything else gets copied including the file descriptor gets copied but iBinder essentially gets passed as a reference which is how the client thing for example submit a listener to the service so the service can notify the client of changes of some state via callbacks so in that case the roles change the client when it sends something that's of type iBinder it's essentially becoming a service so the client becomes a service and the service that invokes that callback functionality becomes the client to the original client so however what if you had your own data type something that you know you could not basically you know doesn't match one of these so what you would do is you could then create your own custom data class you would just in that class may have you know internally data structures of whatever so you can have whatever you want it in there but the key to making it work with binder is to implement what's known as parcelable parcelable is an interface that requires you to basically create a strategy for writing a fixed strategy for writing basically your object into a parcel and that means boiling down to the primitives that are supported as well as a mechanism for converting a parcel back into that object so for example if you're sending bar to the service the proxy will call this method to convert your bar into a parcel and when the service receives this parcel you will connect the stubble call this method to convert that parcel back into the original bar so as long as the two mechanisms match that will work out of the box i'm not going to go into more details than that you can basically you know primitive you know primitive values don't require for example directional flag and what not commons get copied and so on and so on that's beside the point you can read it on your own let me just mention this briefly binder basically is you know supports these references like i said that can cross object boundaries and somehow remain unique this is key because for example if a service were to register itself with the service manager let's say a location service register itself with the service manager what and now the client asks for that handle well that handle needs to work in the client just like it did in the service manager right so these handles need to be able to be shared so what happens is that when you're creating these binder objects the kernel that binder doesn't know anything the kernel binder driver doesn't know anything about him because you know they're just local binder object but whenever you send a binder object across essentially the process boundary i through the kernel driver the kernel driver notices that that's a binder object and really essentially creates an internal mapping that remembers that that object points to your process and it then creates a handle that it sends to the other side if the other side ever references that handle actually the other side now gets essentially that pseudo handle but on the other side you need a local binder object you need a local object that represents the remote object so there's a local reference to what is essentially you know your object so that the local reference essentially gets some arbitrary you know not arbitrary but some sort of a pointer if you will in your own local local memory space but whenever you then later on invoke an operation where you're writing that memory address to the kernel driver i you're referencing that essentially the kernel rewrites that local pointer back to that kind of generic pointer if you will or the handle and then maps it to what actual process is supposed to have that so there's basically state that is inside of the kernel driver that does the mapping of local pointers to these global if you will pointers and along with that it does reference counting so that he knows how many times a particular object is being used because he knows who you know he gave it to so this is key because this way we can discover when something for example dies or if something is no longer needed the kernel driver can automatically tell the service that is no longer needed so for example service can take it out of service so i'm not going to go into more details on that again we're just running out of time so let me just briefly mention that there is an example here that i invite you to take a look at where basically i have a flow application called kibrodachi that has a simple ui that looks like this you punch in some number you select which kibrodachi algorithm you want to use whether it's going to be implemented in java or c and whether it's going to be implemented recursively or or iteratively and you click on this button and that button basically is supposed to return the result of that kibrodachi calculation what's interesting is that the actual implementation of this kibrodachi algorithms it happens inside of this service where the ui lives inside of the client right so let me just briefly mention kind of how things work so this is again coming to the application space so if you're writing applications you'll really quickly realize that the services in clients that use binder directly are going to have to depend on a common interface so when you're forced to deal with shared code one of the ways to deal to do that in android well you know essentially so you're not duplicating code is to create a library project if you don't know what that means you'll look it up but basically what i do here is i unfortunately i don't have the time to go into that it's essentially it's a project that itself is deployable but it can be referenced by other projects and any artifacts of a library project is getting incorporated into your project at the built time okay so for example let's say i had i wanted to define a common interface and common data types right so these are the types that are referenced by the client in the service and what i would do is i would create a common project that would make it a library project and inside of the project i would then define my a ideal interface and i would create a file called i people not to serve as their ideal inside of it i would define the business operations and then basically you know that will be the first step unfortunately this uses custom data types so this will actually not generate anything yet until i do something else so i need to define those custom data types so those custom data types in this case i have an object called or class called Fibonacci request whose job is to basically encode the n which is what you want to do Fibonacci on as well as the type of the algorithm you want to use it do it on and in this case that's just a simple enum well because this is a custom data type i can't just put it in a parcel because parcel doesn't know anything about Fibonacci request so in order for this to play well with a framework what i need to do is implement parcelable so how do i do that i just have the implements parcelable which forces me to basically write this method which given some parcel i can convert my object into that partial which essentially means i'm just boiling it down to its primitive notice that enums all i need to do is get its ordinal value and basically i write it as a simple in on the flip side i basically need to recreate this object from a parcel in order to basically deploy it again so i'm not going to go into there's basically the the Fibonacci response which is kind of similar i'm not going to go over it it's not important it's basically just has you know two longs nothing but same same idea so i'm in interest on time i'm just going to essentially move forward um so basically when this is got it when you now grow created this this a ideal file you now want to create a service so how does that work well if this a ideal file was well you know written the tool a ideal will automatically be run by Eclipse and generate this stub in proxy so what you do is you now create a new you know let's say a service project that service project extends the stub by extending the stub you're basically essentially you are a binder object and that forces you to automatically implement all of those interface methods that the stub essentially defined so these are the methods that i had like for example you know fit that you know just a bunch of fit methods these are the business methods it's not important so the implementation of these as you can see it's rather simple you're just here in this case as long as you don't care about this part this part up here the rest of this implementation is pure java and that's one of the key benefits to bind there you don't have some sort of a loop you're not pulling on some file descriptor you're just writing callback methods and what will happen is when a client submits a method and or a thread will be automatically picked from the thread pool and one of the threads will invoke one of these callback methods you just have to essentially do the work and so it makes your service extremely easy to write so of course you have to worry about protecting some shared state if there is any because there could be multiple concurrent requests happening at the same time so in terms of the clients i should at this part i'm going to skip this has to do with how you expose the service to the clients it really depends on whether you're writing an application or whether you're writing essentially a you know a system service with a system service all you need to do is construct this object that we previously created this thing and you just go and say service manager would you be so kind to remember this but service manager will not do that for user services because for security reasons and so you end up having to essentially find another way of exposing it which this talks about and i get i'm gonna run out of time so i'm gonna go into the details of it i just want to mention for the client part the client basically how he uses the service so this just talks about the client this is the whole ui you can literally go through all of this by the way all this code is an ui on github but the client basically just has a reference to the service by an interface but in order for the client to connect to it he needs to get somehow the reference to the remote service this is how he gets it as an i bind their object but the client can't use the i bind their object because it's way too generic so what the client needs is to convert that object into a proxy and this is the one line that basically does that for you this is auto-generated code behind the scenes this will generate a proxy and give it to the client and then when the client when it comes time for the client to use it this is basically all it takes the client says service dot fib that's it it's a submittal request and he gets a response it doesn't know anything about binder at that point the only thing that makes this binder specific is the fact that this can fail with the remote exception that's basically if the service gets you know killed in the in the in the meantime so i'm not going to go into the details of that i also want to invite you to take a look at the asynchronous binder which in this case basically what's different is that by adding this one way keyword for example onto your ideal interface what you're saying to the binder framework is that the client should not block for the service to do the work so the client submits a certain request and goes back to what it was doing so now how does the client get the back the response in this case the client has a listener there it sends to the service what happens is this listener gets passed as a reference and the client gets gets basically the data back that way so there's some threading issues that you have to worry about on the client side when you're using listeners because the callbacks happen on binder threads and if you were to try to update the ui from a binder thread you would basically get one of those exceptions so there's you know then you have to use candlers and whatnot that's where for example messenger makes this easy for you so i'm not going to go into the details of it because again we're out of time i want to mention for sharing memory binder has a limit as to how much data you can pass back and forth and that limit is one meg if you want to share memory one way to do it is to use ash mem so what you do is you basically create an ash mem region of certain size you put your data into that region and then you send the file the script to that region to the other side if they want to get access to it again i'm not going to go into details you can read it on your own um other limitations binder has a limit up to 15 concurrent threads on the on in each process so that means that you're basically can up to 15 things happening through the binder framework for a given process so for example if the service happens to be doing some blocking work right so it's better not to do it in a binder thread but rather spawn its own thread to do that blocking work and allow the binder thread to go back to the pool and service some other requests especially if that was written to be asynchronously we say synchronous to begin with in terms of security i'm just going to mention that there can only be one service manager at any given time for security reasons and that one service manager by default does not allow untrusted services to bind with it the which is why when you're writing application level services you end up having to go through this kind of roundabout way of binding it this just talks about how this is done and finally i want to mention that one of the key features of binder is that it sends the information about the client to the service for every request which is then used by services to figure out who the clients are and then based on that information figure out whether those clients should be authorized to make access or essentially invoke those operations so almost all of the application framework services in android are enforced this way although like for example let's say vibrate let's say you wanted to vibrate a device well before the vibrate happens the very first thing that happens is it checks for whether the caller has the permission to vibrate the device and the permission isn't granted you get an exception or for example if you're talking to location service if you don't have the location to access final location so if you don't have permission to access final location you get an exception how does this work well underneath the hood we just ask binder who are you you're talking to us once we know who you are by your uid we can go to figure out which application you are once we know which application you are we can ask the package manager which permissions have you have been granted to you so it's a it's a it's a mechanism that basically gets used for almost all permission enforcement on android um the rest of the the actually only two more slides and i think we're done um one other feature of binder is this death notification which is very important so for example let's say you go and ask a location service to get you updates every time location changes and then you die because you get a low memory killed or you have some something happens in your process and you forget to unregister well guess what we don't want to cap the gps being you know polling and sending these updates to nobody right or if you ask for a wakelock and you never return it and you die we don't want this wakelock to keep the device awake so what happens is these services basically track the clients basically through binder and they get notified when the clients die and they automatically do cleanup on the client side when that is detected there's these so-called as you'll see you can link to death of any binder object and then once you basically get notified as a death recipient you can for example you know remove you know that object from for example you know being updated or something out of like you know you can shut down whatever you were doing on on behalf of that object it's actually very key to how android manages resources had it not been for this we'd be really hard for android to basically avoid these sort of you know essentially bad applications you know creating denial of service or things and then finally reporting binder has a full you know and through the proc file system or through the debug file system basically reports on these transactions which i wish i had time to show you but you can kind of try it on your own and see what happens there's a whole bunch of other resources i invite you to check out you know a lot of you know good slides and and and essentially discussion of android of binder and open binder that's that's worth looking at and so again in summary we took a look at what binder is kind of compares to others briefly how it works you know i've briefly talked about how you could implement it i invite you to take a look at the code we talked about features like a ideal the security and death notification and so on and so on this record this talk will be recorded or actually is being recorded i'll save it and later on upload it to the same URL i'd like to check it out and hopefully you guys got something out of it so thank you i'll be here if you have any questions