Tuesday, February 21, 2012

C Language: Struct packing and member alignment.

I know this has been discussed and re-discussed at so many locations and so many times that me writing about it again wont make much of a difference but I still see so many people confused about this that I cant stop my self from writing about it.

By default C compilers properly align each member of struct. This means that a 2-byte member e.g. short is aligned on 2-byte boundary, a 4-byte member e.g. int is aligned on 4-byte boundary and so on. This is done so that the struct members can be accessed efficiently and to reduce cache misses. To ensure proper alignment compilers add padding bytes to structs. Consider for example the following struct:
struct SomeData
{
    char Data1;
    short Data2;
    int Data3;
    char Data4;
};

Now as you can can see we are only using 8 bytes for data, but the compiler will add padding bytes to this struct to ensure proper alignment of its member. So a variable of this struct type will actually be like this after compilation on a 32-Bit machine:
struct SomeData
{
    /* 1 byte */
    char Data1; 
    /* 1 byte so the following 'short' can be aligned on a 2 byte boundary*/
    char Padding1[1]; 
    /* 2 bytes */
    short Data2;
    /* 4 bytes - largest struct member */
    int Data3;
    /* 1 byte */
    char Data4;
    /* 3 bytes to make total size of the struct 12 bytes */
    char Padding2[3];
};

The compiled size of the structure is now 12 bytes. It is important to note that the last member is padded with the number of bytes required to make total size of the struct a multiple of the size of the largest member of a struct. In this case 3 bytes are added to the last member to pad the struct to the size of a 12 bytes (4 bytes of int × 3).

As you can see, we are wasting memory. We can off course stop compiler from doing this by asking compiler to pack structs tightly (using #pragma pack() with gcc) but then we lose performance benefits of proper alignment.

In order to avoid these padding bytes but still have proper alignment, we can rearrange this struct so that larger members are listed before the smaller ones. So the above struct can be rearranged as:
struct SomeData
{
    int Data3;
    short Data2;
    char Data1;
    char Data4;
};
Now this does not require any padding as every element is already properly aligned and the overall size of the struct is a multiple of the largest member i.e 4*2 = 8. This is off-course just an example and in reality, even if you arrange your struct members this way, there will still be some padding at the end of the struct to make total size of the struct a multiple of the size of the largest struct member
So please always arrange members of your structs in decreasing order of their size.

Thursday, February 16, 2012

Android: How to start vendor specific Alarm Clock on any Android device?

Alarm clock is a nice to have feature for many applications and because of Intents you dont need to code this functionality in every app where you want it. For Android, adding an Alarm Clock to your application is as simple as launching an Intent for the built-in Alarm Clock of the device. The only issue here is that different manufacturers i.e HTC, Google, Samsung, Sony Ericson have their own implementation of Alarm Clock and there is no single intent that will automatically launch which ever Alarm Clock is present on the device. So to start Alarm Clock, you will first need to check which Alarm Clock is present on the device that the app is running on and then launch that Alarm clock.

The code below is what I used in one of my recent apps:
private void startAlarmActivity()
{
 PackageManager packageManager = getPackageManager();
 Intent alarmClockIntent = new Intent(Intent.ACTION_MAIN)
                                     .addCategory(Intent.CATEGORY_LAUNCHER);

 // Verify clock implementation
 String clockImpls[][] = {
    { "HTC", "com.htc.android.worldclock",
    "com.htc.android.worldclock.WorldClockTabControl" },
    { "Standard", "com.android.deskclock", 
    "com.android.deskclock.AlarmClock" },
    { "Froyo", "com.google.android.deskclock", 
    "com.android.deskclock.DeskClock" },
    { "Motorola", "com.motorola.blur.alarmclock",
    "com.motorola.blur.alarmclock.AlarmClock" },
    { "Sony Ericsson", "com.sonyericsson.alarm", "com.sonyericsson.alarm.Alarm" },
    { "Samsung", "com.sec.android.app.clockpackage", 
    "com.sec.android.app.clockpackage.ClockPackage" } };

 boolean foundClockImpl = false;

 for (int i = 0; i < clockImpls.length; i++)
 {
  String packageName = clockImpls[i][1];
  String className = clockImpls[i][2];
  try
  {
   ComponentName cn = new ComponentName(packageName, className);
   packageManager.getActivityInfo(cn, PackageManager.GET_META_DATA);
   alarmClockIntent.setComponent(cn);
   foundClockImpl = true;
   break;
  }
  catch (NameNotFoundException e)
  {
   Log.d("ADNAN", "Alarm clock "+clockImpls[i][0]+" not found");
  }
 }
 if (foundClockImpl)
 {
  alarmClockIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(alarmClockIntent);
 }
}

Thursday, February 9, 2012

Android: How to transform/scale a bitmap and draw it on Canvas without losing quality

If you want to rotate a bitmap and paint it on a Canvas in an Android app, you will probably use Canvas.rotate(degrees) to rotate the canvas and then paint your bitmap using any of Canvas.drawBitmap methods. Nothing fancy but the painted image will be too pixelated - except when the rotation is in multiple of 90 degrees.

The last argument to all Canvas.drawBitmap* methods is a Paint object and most of the examples I found on internet were passing a null for it. To avoid, rather reduce, the pixelation we need to use this Paint object. Create a paint object as mentiond below and pass it as a last argument to your drawBitmap() call.
Paint paint= new Paint(Paint.FILTER_BITMAP_FLAG |
                       Paint.DITHER_FLAG |
                       Paint.ANTI_ALIAS_FLAG);
This will significantly reduce pixelation and your app will look a lot better.