Monday, April 19, 2010

Android Input Software Nightmare

Lets now look at the wonders of Android Input. I was trying to get a touchscreen to work.

The first challenge is that the Android input code was not designed to handle any device that requires calibration. It assumes that the ABS_X/Y coords that come from Linux input is already screen accurate. Sure, that works fine on your factory calibrated capacitive HTC Booyah but it doesn't quite meet the needs of many common technologies like resistive, let alone flexible touchscreens. Okay, nevermind, I implemented a workaround transform and I'm able to get past that.

Next challenge. Lots of odd behavior. CPU utilization at 70-90% just for drawing on the screen. What's going on? Meanwhile, other issues as well. Semi functional touch. Sometimes picks up gestures fine, sometimes not. When drawing slowly, stuff works mostly okay. Draw fast, and a curve becomes a straight line. What's going on, dropping samples? data flooding?

It wasn't the hardware. It wasn't the driver. It wasn't Linux input. So, I started looking at the wonderful Android input layer code.
a) KIQ
588 synchronized (mFirst) {
589 // NOTE: The event timebase absolutely must be the same
590 // timebase as SystemClock.uptimeMillis().
591 //curTime = gotOne ? ev.when : SystemClock.uptimeMillis();
592 final long curTime = SystemClock.uptimeMillis();
593 final long curTimeNano = System.nanoTime();

Hmm. Suspicious.

775 me = ms.generateAbsMotion(di, curTime,
776 curTimeNano, mDisplay,
777 mOrientation, mGlobalMetaState);

Hmm. Generating motion needs to store nanosecond accurate time of every single sample? Ok. Maybe there are good reasons for that.

783 if (me != null) {
784 if (WindowManagerPolicy.WATCH_POINTER) {
785 Log.i(TAG, "Enqueueing: " + me);
786 }
787 addLocked(di, curTimeNano, ev.flags,

663 if (currentMove != null) {
664 if (false) Log.i("InputDevice", "Adding batch x="
665 + reportData[MotionEvent.SAMPLE_X]
666 + " y=" + reportData[MotionEvent.SAMPLE_Y]
667 + " to " + currentMove);
668 currentMove.addBatch(curTime, reportData, metaState);
669 if (WindowManagerPolicy.WATCH_POINTER) {
670 Log.i("KeyInputQueue", "Updating: " + currentMove);
671 }
672 return null;
673 }

um-huh-what? generate motion and then the result is intentionally typically null? Look through the code history. Maybe there's a patch I can pick up that'll fix my problems. Oh, wonderful, nice, confident developments like:

"Maybe fix issue #2145012: Array bounds exception in touch event processing"

This software looks like rasam. Great swearware Googlers. Okay, give up trying to understand their code. Lets see what other people have discovered. Oh, great: Known Issue 7836. Check these excellent cpu utilization numbers just for doing input:
36% CPU usage on my G1/1.6

Nice. The CPU vendors must love Android. But I'm frustrated and exhausted. I'm going to sleep and hope to wake up from this nightware.

Labels:

Friday, April 16, 2010

Android shell

Lets look at the android shell, /system/bin/sh . By default, the build comes out with a shell that has no history, no tab completion, doesn't handle backspace or delete and various other excellent features. There's no easy way to switch to a recent shell because there's no automake and bionic has various other issues so those who enjoy more pain solve it by copying a staticly built busybox from some other build system. But... they're missing out. The great benefit of this Android shell is it provides regression therapy for embedded folks. Its like going back into 2002, or better known as 3-AB (3 years after busybox). You then poke at the shell code in the Android tree, praying to the spaghetti monster PBUH(er) that there's an ifdef IN_2010_NOW and instead, in their build scripts, you see stuff like:
make_ash_files:
p4 edit arith.c arith_lex.c arith.h builtins.h builtins.c
p4 edit init.c nodes.c nodes.h token.h

1999, here we come. :-) Is Vajpayee still prime minister?

Labels:

Sunday, April 11, 2010

Thoughts on the iPad

I saw remarks like John Gruber's "E-Ink RIP" and was surprised. Do people actually believe that the iPad somehow resurrected LCD technology? Has it changed LCD displays in some way and somehow enhanced their technical capabilities? No, the iPad just uses ye olde 9.7" 1024x768 18-bit IPS LCD. It's a good display, maybe even a great display for the iPad's purpose, but still... just another LCD, just the same currently dominant, good enough but boring electronic display technology that this planet will probably continue to have for another -2 to 8 years depending on application category. E-Ink technology on the other hand, especially the new "just making its way through the production floor flexible and color enabled" technology excites me. I wouldn't be surprised if iPad v2...

Labels: ,

Saturday, April 03, 2010

Reading Android code

I'm trying to like Android code but failing. I want to share today's challenge. Here is top of tree Android EventHub code. When a device is removed, it does close_device which does things like:

for(i = 1; i < index =" (device-">id&ID_MASK);
mDevicesById[index].device = NULL;

close(mFDs[i].fd);
int count = mFDCount - i - 1;
memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
mFDCount--;

You see the memmove-s and think, hmm, odd, wonder what they're trying to do. You look in open_device:
    int devid = 0;
while (devid < mNumDevicesById) {
if (mDevicesById[devid].device == NULL) {
break;
}
devid++;
}
   mFDs[mFDCount].fd = fd;
mFDs[mFDCount].events = POLLIN;


and you see what looks like an attempt to map a device ID to a collection of data associated with it, most importantly its fd. It looks like a very odd way of doing it, but hey, if it works , then great, we can just ignore above oddness and go on with our lives. Problem is, that this stuff doesn't work. Even for simple things! When a device is removed, and then plugged back in, Android userspace fails in exciting ways.

Lets work an example. The first device that had been added has devid 0, and when it is removed, the other devices are pulled back with the memmove of mFDs and mDevicesById[0].device entry is set to null. But then those devices that were pulled back haven't had their IDs changed, so the:


#define id_to_index(id) ((id& ID_MASK)+1)

if (ioctl(mFDs[id_to_index(device->id)].fd,


results in the wrong fd being used for everything else since id n was memmoved to n-1 and the id_to_index doesn't account for that. The new device then picks up devid 0 (since that was the first mDeviceById[].device that was null) and then everything fails since mFDs[mFDcount] and count is 8 so it fails. fails. fails. :-( Sad. Okay, going to lunch now.