Android podcast notes

December 8th, 2007

Notes from the recent Android podcast…

  • Dalvik VM can mmap dex files.
  • Zygote loads VM before forking, so copy-on-write effective and all apps share lots of pages.
  • ‘am’ command doesn’t work that way; can get idea of benefit; takes 2 seconds to launch because it has to load all classes.
  • Different user for each application. Your data is UID’d to you on the filesystem too.C
  • Content providers use URL scheme. Every bit of data on device has a unique name.
  • Intents are just a generic way of naming something to do. e.g. I’d like a content. Then system finds something like the contacts app. Similar for playing an MP3, any media player app can fulfil intent.
  • Intents are broadcast; anyone can reply.
  • Embedding in UIs not supported.
  • XML gets compiled down. Generic binary format for XML, the compiler can reduce any XML.
  • Reference HW has 64MB RAM, 128MB flash. No virtual memory practically. Yet Linux is aimed around VM. For example when creating a thread, Linux allocates a heap of virtual address space for the program (but only allocates physical pages later). If RAM unavailable, would have to kill app, can’t fail the malloc.
  • So component model allows kernel to identify which applications aren’t needed, and kill them if there are insufficient pages.
  • Threads: tried hard to avoid needing an app to have multiple threads. Everything designed to happen in main thread. But of course you need to remain responsive in main thread.
  • A service is not a main thread either. When you start a service it runs on the main thread still.
  • UI framework not thread-safe, for efficiency. Must access UI object from main thread. Use Handler object to do that.
  • Handler also allows timer services; can request an event in the future.
  • Current UI is somewhat of a placeholder

Updated openbinder.c for strace

December 5th, 2007

Here’s my latest openbinder.c file (use with the other changes in my previous post).

openbinder.c

Much more sensible output this time. I was right to be suspicious about all the nulls – it turned out I was only transferring the first byte of the data. But still no strings yet… next is to decode the replies from the kernel, then to read the kernel module source a little more closely to work out if we can decode any of the stuff in ‘buffer’. Plus, of course, to keep working on it to see if I’ve made any other daft mistakes :-)

Example output:

22:34:57.044758 ioctl(7, BINDER_WRITE_READ, {write_size=56,write_consumed=56,write_buffer=0x153f8,read_size=256, read_consumed=8,read_buffer=0x152e8,write_data= [bcINCREFS(target=0x00000015)bcACQUIRE(target=0x00000015) bcREPLY({cookie=0x00014130,code=0x00000000,flags=0x00000000,priority=80,data_size=12, offsets_size=0,data={buffer=0x00015970,offsets=0x00000000, *buffer=[0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,............]}})], read_data={...}) = 0

22:34:57.867208 ioctl(7, BINDER_WRITE_READ, {write_size=40,write_consumed=40,write_buffer=0x153f8,read_size=256,read_consumed=8, read_buffer=0x152e8,write_data=[bcREPLY({cookie=0x00014130,code=0x00000000, flags=0x00000000,priority=80,data_size=24,offsets_size=4,data={buffer=0x00015e18, offsets=0x00014130,*buffer= [0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x85,0x2a,0x68,0x73,0x08,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x04,0xfe,0x4f,0x10, .........*hs..........O.]}})],read_data={...}) = 0

So far the only decent string I’ve seen in any of the buffers is /dev/input/event0… which might give another clue about where to head next.

Beginning to decode Android IPC

December 2nd, 2007

I’ve had a quick look into the OpenBinder ioctls zinging around within the Android emulator. Here’s a summary of what I’ve done, and the results I’ve had (such as they are… it’s not been too fruitful).

First, the context. We know that Android IPC uses a system called OpenBinder, thanks both to Benno’s pioneering investigations, and the fact that one of the OpenBinder developers kindly posted a load of information on the web! But, we also know that the user-side OpenBinder is not based on the existing MPL version, or Google would have had to release the code already. (For this reason a lot of my terminology is probably wrong – it looks like perhaps the MPL version is OpenBinder, whilst we’ve got some other type of Binder, perhaps a not-quite-Open-yet-Binder).

In fact, the only code we’ve got relating to the OpenBinder in use within Android are the code for the module, provided within the Android Linux kernel. That includes two header files – include/linux/binder_module.h being the important one – and about 10 files code for the kernel-side driver.

According to the OpenBinder website, the kernel driver is responsible for reference-counting as well as the pure data-copying aspect of IPC. So, with any luck, the kernel-side code will have to understand the data structures passed back and forth, and therefore so can we.

Anyway, this is what I did.

  1. First, I modified strace to output some information about OpenBinder. I only bothered with the BINDER_WRITE_READ ioctl, and essentially just printed out the payload in binary, for the moment. My changes are here – sorry it’s not a nice easy patch, but all the makefiles etc. got changed too and I didn’t want to include them in the patch. strace-4.5.15-diffs
  2. I built this using my Scratchbox as per my previous instructions. You’ll need to run automake first to rebuild the makefiles to include the extra source code file.
  3. I then followed Benno’s instructions to boot Android without the automatic startup of Zygote and the runtime. I ran my modified strace in exactly the same way as Benno to get the output I wanted.

Enough! What are the results? Well… not very spectacular yet.

Here’s a typical ioctl:

ioctl(7, BINDER_WRITE_READ, {write_size=8,write_consumed=8,write_buffer=0x14eb0,read_size=256, read_consumed=44,read_buffer=0x14da0, write_data={0x4,0xc1,0xb,0x0,0x84,0xc1,0xb,0x0,}, read_data={0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb9,0xfc,0x1,0x0,0xe,0x0,0x0,0x0,0xb1,0xfc,0x1,0x0, 0xe,0x0,0x0,0x0,0xa9,0xfc,0x1,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}) = 0

My thoughts about that (in no particular order):

  • I don’t like the fact that the write_buffer and read-buffer addresses are so small. I am not at all familiar with the Linux memory map, though, so maybe Linux process memory really does start all the way down there. And, their type is signed long. (In standard OpenBinder it’s void*, according to the documentation). Comments suggest that this strange type is used to allow for mixed 32/64-bit systems, but I still slightly worry that these parameters aren’t addresses at all, but could be offsets into some shared mmapped area or something.
  • However, each time I tried to fetch the data at this address, it worked. So this makes me think they’re real addresses.
  • I think these data areas should contain lists of commands and replies, respectively. The commands and replies are variable-length, so without some analysis it’s hard to work out second and subsequent commands/replies. The first byte is an opcode from BinderDriverCommandProtocol. I’m encouraged that the first byte is never 0×0, which would be bcNOOP, and is small enough to be likely to be an enumeration. So again, I’m happy these are the command streams.
  • But I’m surprised we’re seeing so much null data. I’d also hoped that we’d see some strings related to the objects being bound to. But perhaps they’re pointed to by pointers within the data stream (certainly, the main ‘transaction’ command usually contains pointers to the real data).
  • Maybe the read_data is usually blank; the client always allocates 256 bytes for a reply. Quite often the first opcode in the reply is 0xe, no-op, which might back that up. Although I’m not clear how the no-op operation causes the rest of the buffer to be ignored.

The code within the kernel module does parse and try to understand this data, and it does match the understanding above.

My overall conclusion: this approach does work, and it’s just a matter of getting time to implementing code within strace fully to parse the Binder command stream. I reckon we should be able to get as far as tracking individual object lifetimes, and what method are called on which objects. I reckon we should be able to get the names of the objects (as that’s part of the binding) but I haven’t yet worked out how binder specifies the methods which are called… it’s probably by ordinal into the interface rather than by name, so perhaps we won’t be able to work out what methods are being called. We’ll see, though. It would be great if we could see what methods were being called by one process on another.

You might wonder why I stopped here… mostly because I ran out of time, but also because I planned to do the analysis using Perl from this point onwards. But I think we’re going to need to access pointers to other bits of memory, so strace is probably the way to go.

(It might be easier just to rebuild the kernel with binder logging turned on, but I haven’t yet tried rebuilding the kernel for Android).

Here is an archive of the strace logs retrieved. Logs

I hope I will eventually get around to implementing much more code within strace to dig into what Binder is up to, although I reckon Benno’s bound to get there first :-)

Using Scratchbox to build complex ARM binaries for Android

November 25th, 2007

Benno explains how to build simple native programs for Android. But any significant pre-existing Linux software package uses a complex array of libraries and a correspondingly complicated build process, typically based around GNU Autoconf. That build process usually involves a “configure” script whose purpose is to run tiny programs to experiment with the system, to find out its capabilities and set up the code appropriately.

Terrific, except it doesn’t work if, say, you’re building on an Intel x86 box, but trying to build for Android, which is based around Linux and an entirely different CPU. Fortunately, the Scratchbox project exists to solve this problem. It provides you with a special Linux universe, which uses the QEMU emulator to run ARM binaries. Hence: autoconf can run its experiments and all will be well.

It worked surprisingly well and surprisingly simply. Good work by the Scratchbox team.

Maybe this is how Benno produced his strace binary which he used to dig up some interesting stuff from Android. I’m not sure. Either way, I’m going to be building strace here as an example of how to get this stuff to work.

  1. You’re really going to need Linux. Specifically, it sounds like a Debian-based distribution is by far the most likely to work. Since I’ve got a Mac, I had to install Ubuntu Linux 7.10 within a Parallels virtual machine. This is easier said than done, in itself, but once the X-server problems were sorted out it was reliable.
  2. First we need to install Scratchbox. It’s available as Debian packages. You can install it either using command-line tools, or the GUI package manager. So naturally I chose half-and-half.
    1. Edit (as root) /etc/apt/sources.list, and add this line: deb http://scratchbox.org/debian stable main
    2. Use the Synaptics Package Manager (in the System menu) to look at the available packages. You’ll need:
      • scratchbox-core
      • scratchbox-libs
      • qemu (not 100% convinced this is really required; I think it may be provided with Scratchbox)
      • scratchbox-devkit-cputransp

      You’ll also need a toolchain. Which toolchain(s) to choose was a bit of a mystery. I’d like to have seen a package using CodeSourcery’s latest compiler, 2007q3. But it seems the Maemo platform, the main user of Scratchbox, is stuck on an older compiler. To be honest, more of an issue than the compiler is probably the version of libc in use within the Android platform. I haven’t figured that out yet, so I’ve been producing statically linked binaries for the moment. Anyway, for my toolchain, I chose scratchbox-toolchain-arm-linux-2006q3-27, which appeared to be the most recent.

    3. Wait for these to install…
  3. As per the Scratchbox install document and these Maemo-focussed instructions, add your user to scratchbox: sudo /scratchbox/bsin/sbox_adduser adrian
  4. Log out and log in again until the groups command reveals you’re in the sbox group
  5. Run scratchbox
  6. Run sb-menu
  7. Create a new target. Configure it thusly:
    1. Select the compiler you installed, arm-linux-2006q3-27
    2. Select cputransp devkit
    3. Select qemu-arm-0.8.2-sb2 emulation
    4. No to rootstrap
    5. Yes to files. Choose C-library, /etc, Devkits and fakeroot
  8. Scratchbox screenshot

  9. Exit sb-menu. You will be deposited back at the scratchbox shell, but this time the shell is able to run ARM binaries. So things like configure should work.
  10. Fetch your source. I built /scratchbox/packages/hello-world.tar.gz and also strace 4.5.15. In theory you ought to be able to build anything (so long as static linkage is OK, and so long as the configure script doesn’t do anything too wacky that qemu can’t emulate). For your first build, perhaps stick to the hello world example?
  11. Unzip it/install it/etc. into your scratchbox home. What appears to be /home/xyz is actually located at /scratchbox/users/xyz/home/xyz so that’s where to put the files. (The reasons scratchbox maintains a separate root is so that there’s no chance any of your important system files can be blatted whilst building things for a different architecture).
  12. ./configure LDFLAGS=--static (that’s minus-minus static, in case the blog software munges it)
  13. make
  14. That’s it! You now need to move the generated binary from here onto your Android emulator in the tried and trusted way, then execute it:
  15. MacBook:Desktop adriantaylor$ file hello
    hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.14, statically linked, for GNU/Linux 2.6.14, not stripped
    MacBook:Desktop adriantaylor$ cd android_sdk_darwin_m3-rc20a/tools/
    MacBook:tools adriantaylor$ ./adb push ../../hello /system/bin/hello
    2006 KB/s (563210 bytes in 0.274s)
    

    In my case, rinse and repeat for strace, then…

    MacBook:tools adriantaylor$ ./adb shell
    # /system/bin/hello
    Hello World!
    # /system/bin/strace /system/bin/hello
    execve("/system/bin/hello", ["/system/bin/hello"], [/* 8 vars */]) = 0
    uname({sys="Linux", node="(none)", ...}) = 0
    brk(0)                                  = 0x80000
    brk(0x80c70)                            = 0x80c70
    syscall_983045(0x80430, 0x7dd88, 0, 0x10, 0x80430, 0x7e734, 0x7ea38, 0xf0005, 0x28, 0x8, 0x4, 0x10, 0, 0xbe94cb08, 0x11da8, 0x8834, 0x60000010, 0x80430, 0, 0, 0, 0xc8c8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0
    brk(0xa1c70)                            = 0xa1c70
    brk(0xa2000)                            = 0xa2000
    fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000
    write(1, "Hello World!\n", 13Hello World!
    )          = 13
    munmap(0x40000000, 4096)                = 0
    exit_group(0)                           = ?
    Process 547 detached
    

Maybe I’ll eventually get some time to get dynamic linkage working, which shouldn’t be too hard, just a matter of working out which libc to use. Famous last words?

Update: yes, dynamic linkage may be too much to hope for. The libc is apparently derived from BSD rather than glibc. And I can’t get these tips to work.

IPC on Android

November 19th, 2007

A couple of links: some investigation and some more information on it.

Java class loaders: a good interview question?

October 23rd, 2007

Java is widely regarded as easier to develop for than C++, etc. I tend to agree with that. In C++ it’s easy to find some nasty question to separate the decent developers from the amateurs (for example, ask them how a vtable works).

But even Java has some “low-level” lurking features which only the better Java developer understands. One of these is the class loader. Java normally has a class loader which will search the CLASSPATH environment variable, and/or any JAR file specified, when asked to load a given class. But this can be replaced – and often is.

For example, in Eclipse, each plugin has its own class loader. This means that plugins cannot conflict by having two classes with the same name; it also means that Eclipse can enforce a clear dependency tree on the plugins (the classloaders interact to allow downstream plugins to load classes from upstream plugins).

More or less the same applies to J2EE environments on web servers. Again, this is done so that the different… errr… web thingies have separate environments.

Still other classloaders – such as for good old Java applets – load classes dynamically across a network.

I’m hardly an expert on this stuff, but it seems I know more than some. The vendors of a library I wanted to use load their configuration files using getResourceAsStream(), which is delegated to the class loader. I explained this wasn’t very convenient for people whose class loaders didn’t refer to useful directories. They said that I should just edit the CLASSPATH and insisted that “all Java environments have a CLASSPATH” despite me repeatedly telling them it’s not true. For Eclipse and web applications, at least, the CLASSPATH is irrelevant.

The library is popular and otherwise appears well-designed and reasonably well-written.

All of which makes me think that any decent Java developer would be able to answer an interview question such as “what are some advantages of using a different class loader?” as a good filter at interview for Java developers.

Having said that, I’ve always been rubbish at interviewing so don’t listen to me.

Plural number formats in Excel

October 10th, 2007

In Excel, suppose you want to produce a table like this:

2 oxen
1 ox
3 oxen
Total 6 oxen

Obviously you want to use the SUM formula to add up the total number of beasties. That means you can’t literally type “2 oxen” into the cell – you’ll have to just type “2″ but make up a number format to present it as you wish.

That’s easy for singular quantities: the number format would be 0 "sheep".

But for plurals you have to go a bit further. It turns out you can put multiple formats in the box, separate them with semicolons, and add conditions. So the desired format is this: [=1]0 "ox";0 "oxen".

This adds all sorts of potential. What about [=0]"None";[<4]"A few";"Lots"? Or [=2]"Company";[>2]"A crowd"?

Small screens plus Eclipse

October 5th, 2007

I’ve found a neat way to survive using Eclipse on a small screen!

Get rid of the Outline view (I did that ages ago). That frees up a third of your screen which you can devote to code.

The cunning bit is – then – to use Ctrl-O to bring up the Quick Outline view, and type the first few letters of the thing you wish to navigate to. Quicker than using the Outline view in the first place, and takes no screen space!

Displaying help in Wizards in Eclipse

September 27th, 2007

I haven’t seen this full sequence written down anywhere (only in various partial fragments), so here it is for anyone who finds it useful. Here’s what you need to do if you want to add a Help button to your Eclipse wizard.

  1. In your wizard class, call setHelpAvailable(true).
  2. In your wizard page class, override performHelp() with code like this:
    public void performHelp() {
      PlatformUI.getWorkbench().getHelpSystem()
        .displayHelp(CONTEXT_ID);
    }
    
  3. CONTEXT_ID should be something like “ .mywizardhelp”.
  4. Add a help context extension to your plugin. It should look something like:
    <extension
             id="com.wotsit.doodah.wizardhelp"
             point="org.eclipse.help.contexts">
          <contexts
                file="helpContexts.xml"
                />
       </extension>
    
  5. Create that helpContexts.xml file in the root of your plug-in. (It can be localised in fragments, incidentally). It should contain something like:
    <contexts>
          <context  id="wizardhelp">
            <description>Gets help about this wizard</description>
            <topic href="html/wizard.html"  label="My wizard help"/>
            <topic href="html/toc.html"  label="General help"/>
      </context>
    </contexts>
    
  6. Finally, of course, create the help HTML itself (which you probably did already if you selected the easiest settings when creating your plug-in in the first place).

The bit I couldn’t find documented anywhere was the single line of code which ties it all together! So there might be a better way to do that, but it seems to work.

Numbering table rows in Word

September 27th, 2007

Useful for test plans, etc.

Insert a field each time you want a number produced, with the formula “Seq XYZ”, where XYZ is any arbitrary label you want. (It won’t appear; it just gives a name to the sequence and ensures that each item with that name gets a unique number).

More advanced tips here.