Friday, December 3, 2010

Effect of Data Traffic Explosion on Mobile LBS

These days it is hard to go to any mobile conference without hearing someone talking about the pending explosion of data traffic volume brought on by the dawn of the Internet video age.  If you haven't tuned into the latest yet, GigaOM has a nice recap on the latest Cisco traffic study.  Is there a correlation between this onslaught of data volume and mobile LBS?  You bet.  Read on.

A key issue in mobile LBS is location accuracy and positioning duration.  Today, a mobile location is typically estimated from either GPS signals or cell towers.  GPS is well suited for high-accuracy LBS applications such as car navigation.  But the consumer applications of GPS have long been hindered by technology limitations such as long signal acquisition time and limited signal coverage.  The recent boom of mobile LBS has largely been fueled by cell-based positioning technologies.  Unlike GPS coverage, cell locations are not only much quicker to obtain but also 100% available both outdoors and indoors.  The accuracy of a cell location depends on the cell size.  The smaller the cell-size, the more accurate the cell-derived location.  This where the looming data explosion will benefit LBS.

A two-part series, titled "The Network Paradox: Meeting the Mobile Data Demand", quoted industry sources as saying that the only way to increase mobile data capacity by more than 9X is to deploy 4 or more times of cell sites.  These new cell sites will lead to at least 2 times reduction of the overall cell size according to cellular traffic engineering rules.

So, mobile LBS will see its better days ahead.

A Gotcha Moment with the View Attribute android:id

When editing layout xml files using Google's Eclipse plugin, the plugin is usually smart enough to flag typos when they cause code generation problems. However, errors that slip through the plugin undetected can cause nasty bugs at run-time. One such error involves the use of the attribute android:id. Usually, an id should be specified like this:

<!-- Correct Syntax -->
<Button android:id="@+id/abutton" />

But the following XML will compile fine without any error:

<!-- Incorrect Syntax -->
<Button id="@+id/xbutton" />

Android will even draw the button on the screen. The gotcha moment comes when you try to lookup this button in the view on a newer (such as Android 2.1) emulator/device:

Button aButton = (Button) thisView.findViewbyId(R.id.xbutton);

The aButton variable will be null after this call! What makes this a particularly hideous bug is that it was actually valid pre-Android 1.6! So apparently, the plug-in and the compiler are made backward compatible to allow the old syntax but not the run-time. Welcome to the bleeding edge...

Tuesday, November 23, 2010

Activity Result: The Secret of Passing Information From a Child to a Parent

When an Activity closes or "stops" in Android, how do we pass information back to the parent that started this Activity? The trick is to use Activity Result following this 3-step design pattern:

Step 1: In the parent activity, start the child activity with startActivityForResult()
public class Parent extends Activity {
   private final void startChildOnClick() {
      Intent intent = new Intent(this, Child.class);
      intent.setAction(MyConstants.ACTION_START_CHILD);
      intent.putExtra("Parent Uid", Process.myUid());
      startActivityForResult(intent, 10);
   }
}

Step 2: In the parent activity, override onActivityResult():
public class Parent extends Activity {
   private final void startChildOnClick() {
      Intent intent = new Intent(this, Child.class);
      intent.setAction(MyConstants.ACTION_START_CHILD);
      intent.putExtra("Parent Uid", Process.myUid());
      startActivityForResult(intent, 10);
   }

   @Override
   protected final void onActivityResult(final int requestCode, 
                                         final int resultCode, 
                                         final Intent data) {
      // !!! Called before onRestart() if the parent was 
      // not destroyed!!!
      super.onActivityResult(requestCode, resultCode, data);
      if (requestCode == 10 && resultCode == 20) {
         if (data != null) {
            int cUid = data.getString("Child Uid");
            // Be careful to when to use the data passed 
            // from child
         }
      }
   }
}
It is very important to understand when onActivityResult() is called in the Activity lifecyle. If the parent activity was not destroyed before it is brought back to the foreground again, the calling sequence will be:
onStop() --> onActivityResult() --> onRestart() --> onStart() --> onResume()
Here, a good design pattern for processing data passed from the child is to delay processing to after onStart() by handing off the data to a Handler.

Step 3: In the child activity, override finish():
public class Child extends Activity {
   @Override
   public final void finish() {
      Intent intent = new intent(this, Parent.class);
      intent.putExtra("Child Uid", Process.myUid());
      // Android will pass the result set here to the parent
      setResult(20, intent);
      super.finish(); // Must be called last!!
   }
}
Note that the child must call call super.finish() as the very last statement in the block.
That's it. Happy hacking!

* Updated on December 01, 2010.

Tuesday, November 2, 2010

Service Binding Workaround in Tab Activity

Calling bindService() from an embedded tab activity can generate an error like this:
    W/ActivityManager( 61): Binding with unknown activity: android.os.BinderProxy@43f4a2d0

A quick googling turned up two bug reports on this problem:
http://code.google.com/p/android/issues/detail?id=2665
http://code.google.com/p/android/issues/detail?id=2483

Apparently, bindService() can not be performed from inside an embedded activity such as a Tab.  There are three workarounds:
  1. Call getParent().bindService()
  2. Call getApplicationContext().bindService()
  3. Call bindService() in the TabHost activity and then passes the binder to other tabs.
Application characteristics should determine which workaround is the best.  But whenver we touch the context object, we should always keep these memory leak prevention tips in mind.

Updated on November 6, 2010:

Because a service connection is context specific, the workaround #1 and #2 can have unintended threading consequences when you use TabActivity and TabHost to manage embedded tabs.  For example, when getApplicationContext().bindService() is used, the ServiceConnection.onServiceConnected() will be called from a thread different from the thread running the current tab.  Therefore, access to the service object must be synchronized.  This is demonstrated below:

public class MyTab extends Activity {
   private static final TAG = MyTab.this.getName();
   private RemoteService remoteService = null;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       if (getApplicationContext().bindService()) {
          // Unsynchronized access!!
          Log.v(TAG, "Service bound ? " + remoteService != null ? "true" : "false";
       }
   }

   private class MyServiceConnection implements ServiceConnection {
      @Override
      public void onServiceConnected (final ComponentName name, 
                                      final IBinder service) {
         // Unsynchronized access!!
         remoteService = RemoteService.stub.asInterface(service);
      }

      @Override
      public void onServiceDisconnected (final ComponentName name)
      {
         // Unsynchronized access!!
         remoteService = null;
      }
   }
}
A straight-forward way to fix the synchronization problem is to introduce a lock variable:
public class MyTab extends Activity {
   private static final TAG = MyTab.this.getName();
   private RemoteService remoteService = null;
   private final Object() lock = new Object();

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       if (getApplicationContext().bindService()) {
          // Synchronized access
          synchroized (lock) {
             try {
                while (remoteService == null) {
                   lock.wait();
                }
             } catch (InterruptedException e) {
                // Recheck condition
             }
          }
          Log.v(TAG, "Service bound ? " + remoteService != null ? "true" : "false";
       }
   }

   private class MyServiceConnection implements ServiceConnection {
      @Override
      public void onServiceConnected (final ComponentName name, 
                                      final IBinder service) {
         // Synchronized access
         synchronized (lock) {
            remoteService = RemoteService.stub.asInterface(service);
            lock.notifyAll();
         }
      }

      @Override
      public void onServiceDisconnected (final ComponentName name)
      {
         // Synchronized access
         synchronized (lock) {
            remoteService = null;
            lock.notifyAll();
         }
      }
   }
}
But we are not all done yet. We must use the same lock variable to pretect EVERY read/write access to the remoteService variable in this class. Why? Because the ServiceConnection.onServiceDisconnected() may be called from the main looper thread when the process hosting the background service has terminated or stopped unexpectedly. This can happen even though a service would normally be kept alive as long as there is a binding to it. Therefore, we need to surround every access to the remoteService variable with a lock to pretect ourself from reading stale object reference.

Wednesday, October 20, 2010

Where Does Android Gets Its Traffic Stats?

Quite simple.  Android get these stats from Linux sysfs and proc file systems.  They can be found at the following locations on a Android powered device:
Android TrafficStats Linux File Location
Android Traffic Stats Table
getMobileTxPackets() /sys/class/net/rmnet0/statistics/tx_packets
/sys/class/net/ppp0/statistics/tx_packets
getMobileRxPackets() /sys/class/net/rmnet0/statistics/rx_packets
/sys/class/net/ppp0/statistics/rx_packets
getMobileTxBytes() /sys/class/net/rmnet0/statistics/tx_bytes
/sys/class/net/ppp0/statistics/tx_bytes
getMobileRxBytes() /sys/class/net/rmnet0/statistics/rx_bytes
/sys/class/net/ppp0/statistics/rx_bytes
getTotalTxPackets() Add up tx_packets for all interfaces under /sys/class/net
getTotalRxPackets() Add up rx_packets for all interfaces under /sys/class/net
getTotalTxBytes() Add up tx_bytes for all interfaces under /sys/class/net
getTotalRxBytes() Add up rx_bytes for all interfaces under /sys/class/net
getUidRxBytes() /proc/uid_stat/[uid]/tcp_rcv
getUidTxBytes() /proc/uid_stat/[uid]/tcp_snd

Inconsistent Life-cycle Events in Andorid Service API

Google Android engineers should read the API design guideline from one of their own.  The callback methods on the Service class violates the basic consistency principle in good API design.  Here is what the SDK doc says about the two callback methods:

"If someone calls Context.startService() then the system will retrieve the service (creating it and calling its onCreate() method if needed) and then call its onStartCommand(Intent, int, int) method with the arguments supplied by the client."

But wait:

"Clients can also use Context.bindService() to obtain a persistent connection to a service. This likewise creates the service if it is not already running (calling onCreate() while doing so), but does not call onStartCommand()."

So, the life-cycle events on Service creation do not occur in a consistent way!  No explanation was given. Sigh...

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.