Google Android is an open source stack for mobile devices . It has a Linux kernel upon which a Java Virtual Machine runs (known as the Dalvik VM). The API is primarily in Java with the added option of writing code in C via JNI and the NDK (Native Development Kit).
The platform is quite comprehensive with most of the JDK standard APIs (java.lang , java.util, java.io, java.net )ported. Each application runs in its own Linux process and each process has its own JVM. An Android application is typically made up of the following components .
- Broadcast Receivers
- Content Providers
Activities represent a single logical action a user might undertake. A Service is like a background process. The Service has no UI. The Service is used to perform long running tasks. A broadcast receiver is designed to pick up broadcasts and filter out the ones intended for the component on whose behalf it is acting. A content provider is a sophisticated mechanism for handling data and data sources.
Fig 1. Android’s Component Model
All of these components are connected via intents. This is of importance to use since it is a loosely coupled design, but a sense of coherency is maintained. Thus this is a good API design technique.
Coupled Design is of 2 types
Strongly coupled systems where in the systems being connected have intrinsic knowledge of each other. This prevents easy replacement of a component.Loosely coupled systems where in the systems just adhere to a communication contract and hence are easily replaceable.
INTENTS as a Message Passing Technique
As indicated above, Intents are a way of achieving communication (light overhead) between the various Android components. Intent specifies the action, the category and optionally data to act upon. Hence, in a single mechanism, data and action is encapsulated.
Maintain a loosely coupled architecture with a simple mechanism to achieve communication between the components. This allows a lot of flexibility when adding newer components.
For example if the API designer wants to add another component, then he can simply add it by maintaining the contract of communication the other components are currently using.This is illustrated by the mechanisms Android has to facilitate communication – Intents and a form of IPC.
Android API provides 2 alternatives for designing the UI (layout and construction) .
- Using declarative style via XML file
- Using procedural style directly via code
Each has its own pros and cons but the main idea is the support of 2 programming styles here! Here we summarize the key differences and tradeoffs between these styles
Maintain several programming styles to the API since each has its own applicability. The declarative style saves time, removes burden from the developer. The procedural style gives the developer a greater degree of control, but adds more burden on coding.
Composite Design Pattern in UI Schemes
The idea is to allow building of custom UI components by leveraging good OO techniques of careful inheritance of classes and implementation of interfaces .
In Android, each user element is called a "View". It forms the parent of a hierarchy known as the "View Hierarchy Tree". This tree implies controlled inheritance relationships. We do not need to stress the importance of careful inheritance in modern OO languages
It is worth noting that this is a description of the Composite Design Pattern. The "View" class is the root of the tree (similar to Swing’s JComponent class ).
If we split the composite design pattern as COMPONENT, LEAF and COMPOSITE, then we would have .
COMPONENT – "View" or "ViewGroup" (which represents abstraction for all components)
LEAF – Actual UI elements like "TextView" or "ScrollView" which represent leaf objects of the composition.
COMPOSITE – The entire UI built up using view elements.
In classic composite style, any operation (like drawing out the UI), requires a traversal of the tree.
Two techniques that offer various degrees of freedom while sub-classing.
First, subclass the most generic class is available. As per our example, "View" or "ViewGroup" would be the most basic types here. Extending these classes provides the developer complete freedom on the appearance of the UI element (in the case of our example) and full control on the functionality (in the more general case). However, care must be taken so that our custom implementation does not distort the concept the class represents to such an extent that it does not adhere to the semantics of its parent class.
Second, subclass various classes lower down in the inheritance hierarchy that is closer to the functionality we wish to implement. Consider the following figure.
Fig 1. Android’s Component Model
Suppose we have some functionality that is closer to "Child2" than to "Parent", it makes sense to subclass "Child2" and make use of the implementations readily available. This may not sound like an API technique but more like common sense. Let us point that good API design is good common sense!
Moreover, this is stated in the Android Custom View Design guidelines.
We will first define security and permissions in the context of android and software.
Remember that Android is basically a Linux kernel and all processes follow the Linux security model for execution and access control .
Bear the following points in mind while reading subsequent paragraphs:
- Each android application runs in a sandboxed Linux process with its own Linux process ID.
- Each application has its own VM instance, hence code runs in isolation.
- All the files created by an application are visible to it only. There are ways to share, but this is through specific techniques only. (Which are outside the scope of this text).
The other point of consideration is Android is a "mobile" operating system. This implies that it must have the facility of controlling access to device functions, execution of 3rd party code.
- Android uses an XML based file to control access to device features.
- Centralized point of access control.
- ONLY the developer can assign/revoke these privileges.
For APIs that are security critical or deal with confidential data, maintaining a central point of control reduces vulnerabilities. But in keeping with Security traditions, there is no perfect solution. Having a central control point reduces vulnerabilities in the system, but is very strict. A compromise must be made depending upon the context of use.
- Modern C++ Style, Bjarne Stroustrup, http://www.artima.com/intv/modern.html http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JComponent.html
- The Design Patterns, Java Companion Guide, James W. Cooper. http://www.linuxtopia.org/LinuxSecurity/