For research purposes, I'm modifying Android SystemServer code.
What am I trying to accomplish?
Whenever there is a call to SystemServer (Binder server process), I want to know the source of this call on the Binder client process; more specifically - the source in my application (e.g., File, Class, Method, etc..).
For example, consider the following code from my app:
public class ClipboardReaderService extends Service {
private ClipboardManager mClipboardManager;
private ClipboardManager.OnPrimaryClipChangedListener mListener =
new ClipboardManager.OnPrimaryClipChangedListener() {
@Override
public void onPrimaryClipChanged() {
String clipContent = mClipboardManager.getPrimaryClip().
getItemAt(0).getText().toString();
Log.i(TAG, "Clipboard content: " + clipContent);
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mClipboardManager = (ClipboardManager)
getSystemService(CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(mListener);
return START_STICKY;
}
}
Using Binder, the corresponding function in SystemServer is being called (and this is where my code should go):
public ClipData getPrimaryClip(String pkg) {
synchronized (this) {
if (mAppOps.noteOp(AppOpsManager.OP_READ_CLIPBOARD,
Binder.getCallingUid(), pkg)
!= AppOpsManager.MODE_ALLOWED || isDeviceLocked()) {
return null;
}
// My code goes here - How can I get the caller method?
addActiveOwnerLocked(Binder.getCallingUid(), pkg);
return getClipboard().primaryClip;
}
}
As I explained above, I have the ability to change the code in SystemServer, and I want to extract the origin of the call on the client side.
What i have tried so far?
So far, I've been trying to extract the client call stack because the information I want should be at the bottom of it.
- Print the stack using
Thread.currentThread().getStackTrace()
- of course this doesn't work, since I print the SystemServer's stack, so I don't see the calls made on the clinet side. - Print stack traces for all live threads using
getAllStackTraces()
- Again, I can't see the client threads since they exist in a separate JVM. - Print the stack in ClipboardManager (i.e., in
setPrimaryClip
function) - It did print the client call stack as expected. In fact, I can pass the call stack as an additional parameter to SystemServer, but then I will have to do this for each function in each service (e.g., NotificationManager) and I'm looking for a more comprehensive solution. - Get the caller uid using
Binder.getCallingPid()
and read the stack from /proc/$pid/stack - That didn't work either, since /proc/$pid/stack only shows kernel stacks.