Wednesday, September 29, 2010

Creating Loadable Kernel Modules for Android

The Loadable Kernel Module architecture in Linux allows a developer to extend the functionality of a pre-built Linux operating system.  We can use this mechanism to extend Android because Linux kernel is the base operating system for all Android devices.  The Linux Kernel Module Programming Guide is the pre-requisite reading before you embark on this journey.  We will use the "Hello World" example from that guide to explain the process of compiling and loading an external Kernel module for Android Emulator.  These basic steps are the foundation for creating custom Android functionality for real-world devices.

The latest Android 2.2 Emulator from the Android SDK does not support loadable kernel modules.  Therefore, the first order of business is to compile a new kernel for the emulator that allows dynamic kernel module loading. 

Prepare the Build Enviornment

The easiest way to compile a Linux kernel for Android is to use build scripts from Android itself.  Refer to my previous blog on how to check out a Android platform build.  From the root of the platform source tree, run:

$. build/envsetup.sh
$lunch 1

Check-out the Kernel Source For the Emulator

Change to a new directory and check out the Linux kernel source for the Emulator.  Note that we must check out the version that matches our emulator because of Linux kernel compatibility rules.  See the Guide for details.  In this example, we use the Android 2.2 emulator from the official SDK.  This emulator uses kernel version 2.6.29.  You can find this version number in Settings or from /proc/version in the adb shell.

$ git clone git://android.git.kernel.org/kernel/msm.git .
$ git checkout --track -b my-goldfish-2.6.29 remotes/origin/android-goldfish-2.6.29 

Configure the Kernel Source

The easiest method to configure the kernel source is to use the configuration from a running emulator:

$ adb pull /proc/config.gz
$ gunzip config.gz
$ mv config .config 


Now edit the .config file and enable the kernel module feature:

CONFIG_MODULES=y

Save the file and proceed to build:

$ export ARCH=arm
$ export CROSS_COMPILE=arm-eabi-
$ make 


Now we have a new kernel that we can use to load our kernel modules.

Compile External Kernel Modules

Create a new directory outside the kernel source tree.  Then create a hello-3.c file and copy-n-paste the source code from the Guide.  Next, create a Makefile to use our own kernel source tree:

KERNELSRC=/mydroid/kernel

obj-m += hello-3.o
all:
    make -C $(KERNELSRC) M=$(PWD) modules

clean:
    make -C $(KERNELSRC) M=$(PWD) clean

Then run make:

$ make


It will create a "hello-3.ko" file after completion.  This is the kernel module that we will use on our Android.  If the kernel source was not configured with "CONFIG_MODULES=y", the compiler would usually throw up an error like this:

error: variable '__this_module' has initializer but incomplete type


Store the Kernel Module onto Android

We first need to use the Android SDK to create an AVD.  In this example, we set the target of the AVD to 2.2.  We then start this AVD with the emulator pointing to our newly built kernel:

$ emulator -kernel /mydroid/kernel/arch/arm/boot/zImage -avd myavd
We can store our kernel module anywhere that is writeable on Android.  No need to "repack" the system image as some on the web has suggested.  The system image from the SDK is not writeable so we will put our file on the user data partition, which is always writeable.

$ adb push /mymodule/hello-3.ko /data/hello-3.ko

Load the Kernel Module

Run the insmod command in the adb shell mode to load our module:

# cd /data
# insmod hello-3.ko

If there is no error, you can verify the new module using the lsmod command:

# lsmod
hello_3 1004 0 - Live 0xbf000000 (P)

You can also verify the module output in kmsg:

# cat /proc/kmsg
<4>hello_3: module license 'unspecified' taints kernel.
<6>Hello, world 3

Congratulations! You are now an Android kernel programmer.  Use your power wisely.

Tuesday, September 21, 2010

Message Object Pooling in Android

The Message object pool in Android is implemented as an unbounded singly linked list. We will illustrate the pooling process with the creation and reclamation of two Message objects.
Initially, there is no Message object in the system. The mPool object, which is the head of the linked list, references to nothing (i.e. is null):

Now, we make the following two calls:
Message m1 = Message.obtain();
Message m2 = Message.obtain();
Since the linked-list pointed to by mPool is empty, Android will create two disjoint Message objects.  There is no linkage between them and the head.
Now, we send these two messages to a handler:
Handler h = new Handler() {
   @Override
   public final void handleMessage(final Message message) {
      // Do nothing.
   }
};
m1.setTarget(h);
m2.setTarget(h);
h.sendMessage(m1);
h.sendMessage(m2);
The Looper in the handler h will dispatch the two messages in the order of m1 and m2.  The dispatch sequence also determines the message reclamation sequence.  The Looper will call Message.recycle() on m1 and m2 after Handler.handleMessage() completes.  Each recycled Message object will be inserted to the head of the list.  So after m1.recycle() is called, the linked list becomes:
Note that the list now has just one element m1m2 is still dangling somewhere in the memory.  Android will call m2.recycle() after m2 is handled.  This inserts m2 into the head of the linked list:
Note that m2 and m1 will not be garbaged collected because mPool is a static reference.  If the linked list is not empty, a call to Message.obtain() will remove the head of the list and return that Message object to the caller.  In other words, no new object is created as long as the linked list has at least one unused Message object.  This design exhibits Locality of Reference.  The mostly recently used Message object is also re-used first.

Wednesday, September 8, 2010

Step-to-Step Guide to Programming Android SSL with Self-Signed Server Certificate

There is a dearth of SDK documentation on how to work with SSL connections on Android with self-signed certificate. Here is a method that stores a self-signed certificate in the application resource and then later uses that certificate for SSL connections.

1. We create a self-signed server certificate for our SSL server:
keytool -genkey -dname "cn=ssltest, ou=test, o=example, c=US" 
   -alias ssltest -keypass ssltest -keystore c:\test\ssltest.keystore 
   -storepass ssltest -validity 180

2. We export the certificate to a file:
keytool -export -alias ssltest -keystore c:\test\ssltest.keystore 
   -file c:\test\ssltest.cer -storepass ssltest -keypass ssltest

3. Since Android uses the JCE provider from Bouncy Castle, we download the provider jar bcprov-jdk16-145.jar from BC and store it at C:\androidproject\libs.

4. Now, we import the server certificate to our Android project as a raw resource:
keytool -import -alias ssltestcert -file C:\test\ssltest.cer 
   -keypass ssltestcert -keystore C:\androidproject\res\raw\ssltestcert 
   -storetype BKS -storepass ssltestcert 
   -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider 
   -providerpath c:\androidproject\libs\bcprov-jdk16-145.jar
Note that we give it a store type BKS.
If you use the Eclipse ADK, the ADK will automatically create a resource id ssltestcert after you refresh the project.

5. We can now use the server certificate in our Java program:
// Load the self-signed server certificate
char[] passphrase = "ssltestcert".toCharArray();
KeyStore ksTrust = KeyStore.getInstance("BKS");
ksTrust.load(context.getResources().openRawResource(R.raw.ssltestcert),
             passphrase);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
tmf.init(ksTrust);

// Create a SSLContext with the certificate
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());

// Create a HTTPS connection
URL url = new URL("https", "10.0.2.2", 8443, "/ssltest");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

/* Uncomment the following line of code if you want to skip SSL */
/* hostname verification.  But it should only be done for testing. */
/* See http://randomizedsort.blogspot.com/2010/09/programmatically-disabling-java-ssl.html */
/* conn.setHostnameVerifier(new NullVerifier()); */

conn.setSSLSocketFactory(sslContext.getSocketFactory());

Congratulations! You can now use your self-signed server certificate for SSL communication.

Programmatically Disabling Java SSL Certificate Check for Testing

Continuous integration testing with Java SSL code is prone to certificate mismatch problems. Sometimes valuable development time can be saved by disabling just the certificate verification logic in the SSL client while preserving all other security logics. This technique is particularly useful for testing with a self-signed certificate because it eliminates the need to install the certificate on every client machine or device that needs to communicate with the SSL server. It is perfectly safe in a well-controlled development environment.

First, we create stub implementations of HostnameVerifier and X509TrustManager.
public static class NullVerifier implements HostnameVerifier {
      @Override
      public final boolean verify(final String hostname,
                                  final SSLSession sslSession) {
         return true;
      }

   }
   
   public static class NullTrustManager implements X509TrustManager {
      @Override
      public void checkClientTrusted(final X509Certificate[] chain, 
                                     final String authType) 
         throws CertificateException {
      }

      @Override
      public void checkServerTrusted(final X509Certificate[] chain, 
                                     final String authType) 
         throws CertificateException {
      }

      @Override
      public final X509Certificate[] getAcceptedIssuers() {
         return new X509Certificate[] {};
      }

Then, we install our stub implementations to the SSL connection.
      // Configure SSL Context
      SSLContext sslContext = SSLContext.getInstance("TLS");
      X509TrustManager nullTrustManager = new NullTrustManager();
      TrustManager[] nullTrustManagers = {nullTrustManager};
      sslContext.init(null, nullTrustManagers, new SecureRandom());

      // Create HTTPS connection
      URL url = new URL("https", "127.0.0.1", 8443, "/ssltest");
      HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
      conn.setHostnameVerifier(new NullVerifier());
      conn.setSSLSocketFactory(sslContext.getSocketFactory());

Configure Jetty Maven Plugin for SSL

Documentation on Jetty Maven Plugin from Eclipse Foundation is not as complete as its predecessor from Codehaus. Here is a sample pom.xml for configuring the plugin for SSL. The highlighted section is the configuration of a SSL connector.
<build>
  <plugins>
    <plugin>
      <groupid>org.mortbay.jetty</groupid>
      <artifactid>jetty-maven-plugin</artifactid>
      <version>7.0.2.v20100331</version>
      <configuration>
        <connectors>
          <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
           <port>8080</port>
           <maxidletime>60000</maxidletime>
          </connector>
          <connector implementation="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
           <port>8443</port>
           <maxidletime>60000</maxidletime>
           <keystore>${basedir}/ssl/server.keystore</keystore>
           <password>sample</password>
           <keypassword>sample</keypassword>
          </connector>
         </connectors>
      </configuration>
     </plugin>
   </plugins>
</build>

Wednesday, September 1, 2010

Will GloPos dethrone GPS?

I don't know why GloPos wants to stake its claims against GPS.  But the short answer to the question in the title is: unlikely.  I will give 4 reasons here:
  1. Wireless emergency services can not use GloPos.  Wireless operators worldwide however must deploy control plane positioning technology and/or GPS to support positioning during emergency calls. 
  2. User plane positioning technology has converged on the SUPL standard.  SUPL enabled handsets and location servers have been commercially available since 2008.  Almost every A-GPS capable smartphone on the market today is equipped with a SUPL stack.  A SUPL server is capable of network-based positioning based on single-cell and multi-cell NMR (Network Measurement Report), which is the same principled technology used by GloPos.  When both wireless operators and OEMs world-wide are investing in SUPL, GloPos will have a tough time to market a competing technology.
  3. NMR positioning is not newTruePosition and Cambridge Positioning Systems were two of the early marketers of this technology 10 years ago.  Their accuracy, confidence and deployment cost claims are even better than those from GloPos if you simply compare their marketing brochures.  GloPos however has not provided any driving test results.
  4. GloPos data cost is too high.  Each positioning session in GloPos requires at least 100Kb data to be transferred, according to this article.  In-car navigation needs a typical 5-second refresh rate.  Thus a 30-minute drive will generate over 4.3MB of data traffic just for positioning alone! 
GloPos seems to have rebranded themselves an "indoor positioning" technology provider since I checked them last September.  But it is interesting that GloPos has now included Google in their competitor category.  Is Google indoor location truly not as accurate as GloPos?  Has any real user noticed a material difference?  Celluar indoor positioning is a hardly a match to short-range radio indoor positioning.  But is GloPos encroaching on SkyHook's turf?