< Binder Shell Syntax | Binder Kit | Binder Process Model >
We use this word in two ways: The Binder refers to the overall Binder architecture; a Binder is a particular implementation of a Binder interface. The name "Binder" comes from its ability to provide bindings to functions and data from one language or execution environment to another.
Any entity that implements IBinder, the core Binder interface. In practice, this generally means a class that derives from BBinder, the standard base implementation of IBinder. A Binder object is able to execute the core Binder operations: inspect, effect (a generalization of put/get/invoke), link, etc.
"Binder Object" is a very general concept: it says nothing about the language used, how the object was created (through the Package Manager or just manually by calling C++ new), the process it lives in, etc. It is simply something that has implemented IBinder, however that may be.
What is the difference between "Binder object" and "a Binder"? Any class that implements IBinder is a Binder object; that class may implement IBinder multiple times for each of the interfaces it supports, and each of those is "a Binder". So a Binder object may have muliple Binders. For example, see BIndexedDataNode, a class that contains two Binders: one for its INode interface, and one for its IIterable interface.
A Binder Object that has been published in the Package Manager. Components are instantiated with SContext::New() or SContext::RemoteNew(), allowing both late binding to the implementation and the instantiation of components in other languages and processes. This is in contrast to instantiating a Binder Object with the C++ operator new, where you must link to a specific C++ implementation and instantiate the object in your local process.
Components use a Java-style naming scheme, such as com.palmsource.apps.AddressBook. Most system components are in the org.openbinder.* namespace.
A Package contains one or more Component implementations. The key elements of a package are (1) the executable code implementing those components, and (2) a "manifest file" that describes the components implemented by that code. The code of a package exports a function called InstantiateComponent(), which is the factory for the components it implements. The Package Manager scans through all of the manifest files in the system to collect information about all of the available components, and returns the information associated with a component as needed.
Note that unlike COM, component information is maintained statically. There is not a Registry-like entity that keeps track of information about the components; instead, a component's information is constructed as needed directly from the manifest file that is part of a package.
The Package Manager is a sub-system of the Binder responsible for keeping track of the available components and implementing the dynamic component instantiation and management facilities.
There are actually two distinct parts to the Package Manager:
- The Package Manager service, published in /packages in the Binder Namespace, is responsible for collecting package information and providing access to it through the Binder Namespace. In particular, it presents under /packages/components all of the available components and information associated with them that is needed to load and instantiate them in a process.
- The SPackage, SPackageSptr, SSharedObject, and BProcess classes are responsible for loading package code into a process, managing its lifetime, providing access to resources in a package, and instantiating objects from it.
Finally, the SContext::New() API brings these pieces together two provide the Binder's formal component instantiation facility: it queries the Package Manager service for information about the requested component, and then calls IProcess::InstantiateComponent() to have that component loaded and instantied in the desired process.
A well-defined set of methods, properties, and events that a Binder can implement. These are usually described in IDL (see interfaces/...
), converted by the pidgen tool to a C++ header and implementation. In C++, instead of deriving directly from BBinder, you will usually derive from some Bn* class generated by pidgen (such as BnDatum), which gives you a BBinder that is configured to implement a particular interface.
Every Interface has an associated Binder. A Binder Object that implements multiple interfaces will thus have multiple Binders, one for each of its interfaces. You cast between these Binders/Interfaces using the IBinder::Inspect() call. Binder Inspect() Details has more details on this process.
The Binder Namespace is a hierarchical orginization of Binder objects. It is constructed using the Binder Data Model interfaces. Directories implement INode, and may implement any other interfaces for additional capabilities (almost always IIterable, very often ICatalog). Leaf objects implement IDatum if they contain a flat data stream (such as a file), but are not required to do so and often implement other interfaces.
Each Binder Object is created in a "context", represented by the SContext object. The context is the thing that holds all of the global state the object can access services, settings, information about components it can instantiate, etc. The SContext you are running in is easily accessible through the BBinder::Context() method. For example, to find the Window Manager service, you would write code within your Binder Object along the lines of Context().LookupService(SString("window")).
SContext is, in fact, just holding the root INode of a Binder Namespace, providing convenience functions for doing common operations with the namespace. Components usually don't get an SContext of the root namespace to enforce security, the system makes additional namespaces that are derived from the root namespace but with modifications such as "can not publish new services".
A previously instantiated Binder object that has been published under /services in the Binder Namespace. These are usually instantiated by the boot script when the system starts up, and exist forever.
You can basically think of them as singleton components, though the Binder does not currently provide any explicit way to define singletons. That is, there is no way to say "this component is a singleton" so that every attempt to instantiate the component returns the same object; instead, you must explicitly instantiate it and publish it in the namespace up front, for others to discover there.
A Link is an active data/event connection from one Binder to another. It is created with the IBinder::Link() method, expressing a binding going from the Binder being called to the given target. The source Binder uses BBinder::Push() to send data through a link.
There are two kinds of links, data and events. All Interface properties are also data links, providing a data-flow mechanism. This can be used, for example, to attach the current value of some property in one object to the value of some other propety in a differnt object; when the value of the former changes, that new value will be propagated to the later.
Event links are created explicitly in IDL in the "event:" section. Events are linked to methods on a target, resulting in a method invocation when the event is pushed.
See Links for an example of links using the Binder Shell.