I don't have the exact solution handy, but the full bore solution involves the TRIAD algorithm to combine the vector from the magnetometer (compass) and the accelerometer. This wikipedia article goes into it in detail .
From a conceptual standpoint the best way to think about the problem is that your accelerometer vector represents "down" and it defines the plane in which in the device is pointing. The tilt of this plane will give you the "roll" and "pitch". You can then use your magnetometer vector to determine where in that plane your device is pointing, and this will give you the "heading".
A robust solution can be implemented with a decent set of vector and matrix/quaternion libraries, but you should be able to hack something together with trig functions. Hopefully another poster has already done so.
EDIT: Found something in the Android docs which looks to provide what you want. You need do get a Sensor object of TYPE_ORIENTATION from the SensorManager. It can provide azimuth,roll, and pitch. I don't know what devices provide this functionality.