Monday, January 30, 2012

Downloading Android source code on Windows

Here's the short-short version:
  1. Download and install command line Git client: msysgit.
  2. Download the root Android project using Git.exe (located in /bin folder of msysgit)
    git clone https://android.googlesource.com/platform/manifest
  3. In the target folder you'll find few XML files. Open default.xml. You can see multiple tags . Choose the project you want to download. You need the name attribute of the project. Write the following line to download:
    git clone https://android.googlesource.com/
Example:
To download the most interesting project (IMHO) frameworks/base, the GIT command is:
git clone https://android.googlesource.com/platform/frameworks/base

Projects of interest:
  • packages/apps/XXXX - The project names of the apps that comes bundled with Android (excluding proprietry Google apps such as the Android Market) such as the Gallery, Camera etc.
  • external/XXXX - 3rd party software (ping, bzip, etc).
  • frameworks/base - The sources of the Java system.

Saturday, January 21, 2012

Android (Java) object pool

There are many ways to implement an object pool. Here's the way it's implemented in some classes in Android (Message, MotionEvent, Parcel, VelocityTracker):

private MyObjectName mNext;
private static Object gPoolSync = new Object();
private static MyObjectName gPool;
private static int gPoolSize = 0;
private static final int MAX_POOL_SIZE = 10;

public static MyObjectName obtain() {
  synchronized (gPoolSync) {
    if (gPool != null) {
      MyObjectName m = gPool;
      gPool = m.mNext;
      m.mNext = null;
      gPoolSize--;
      return m;
    }
  }
  return new MyObjectName();
}

public void recycle() {
  synchronized (gPoolSync) {
    if (gPoolSize < MAX_POOL_SIZE) {
      // Perform object data cleaning and data releasing before recycling
      clearForRecycle();
                
      mNext = gPool;
      gPool = this;
      gPoolSize++;
    }
  }
}

Wednesday, January 11, 2012

Reducing ArrayList add()/remove() memory re-allocation/shifts

This post is Android related, but probably goes to all java systems.

Reason: ArrayList implementation is based on an array, with a pointers to the start and end of the array.
(1) When you remove the first or last items, the pointers are moved. If you remove and items from the middle all the items after the removed location are shifted.
(2) After many removes/adds the start pointer is set so high the ArrayList is forced to shift all the items.

Solution: when removing item - swap the item with the last item, and remove the last item. Drawback - you lose the order of the items in the ArrayList.

import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collection;

public class SwapArrayList extends ArrayList {
private static final long serialVersionUID = 2995040970224168173L;

public SwapArrayList() {
this(0);
}

public SwapArrayList(int capacity) {
super(capacity);
}

public SwapArrayList(Collection collection) {
super(collection);
}

@Override
public boolean remove(Object object) {
int index = indexOf(object);
if (index >= 0) {
int size = this.size();
if (index < size - 1) {
// Swap the last item with the item to be removed
E tmp = this.get(size - 1);
this.set(size - 1, this.get(index));
this.set(index, tmp);
index = size - 1;
}

remove(index);
return true;
}
return false;
}

@Override
public E remove(int location) {
int size = this.size();
if (0 <= location && location < size) {
if (location < size - 1) {
// Swap the last item with the item to be removed
E tmp = this.get(size - 1);
this.set(size - 1, this.get(location));
this.set(location, tmp);
location = size - 1;
}
} else {
throw new IndexOutOfBoundsException();
}

return super.remove(location);
}
}

Sunday, January 8, 2012

onKeyDown/onKeyUp/onTrackballEvent does not fire in a View

When trying to get keypad events in a view, the view does not get those events unless explicitly sent by the Activity, so to fix this add the following code in the Activity:

@Override
public boolean onTrackballEvent(MotionEvent event) {
if (mView.dispatchTrackballEvent(event) == true)
return true;

return super.onTrackballEvent(event);
}