[Android Software Development] Hans Schmucker:
I'm a newbie here, so if you think anything is wrong with this post, feel free to point it out. I'm happy to learn.

I hope it's alright to piggyback on this thread, since half of it (the half of it that doesn't deal with using the linux-way of rebooting) actually deals with the same problem, even though it stems from an entirely different source.

In my case it's about sending a ACTION_PACKAGE_ADDED Intent... what's important is that it's protected the same way:

ActivityManagerService.java: broadcastIntentLocked

if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
|| callingUid == Process.SHELL_UID || callingUid == 0) {
// Always okay.
} else if (callerApp == null || !callerApp.persistent) {

So, it's about satisfying these requirements somehow, or getting around it by sending the broadcast directly.

As you say, you're supposed to sign applications with the same key as the applications in one of these groups to be able to use a sharedUserId, but that's cumbersome and would prevent the application from running on any device other but my own. It would also make updates a lot more complicated... so circumventing it seems the better idea. After all: I am root, so we're already way past any security considerations.

The first thing I've tried is modifying packages.xml , in the hope that the system wouldn't try to re-check the keys. Well, no such luck. From a security standpoint I don't think this check is necessary (if anybody is able to edit packages.xml it's already too late), but Android does it anyway, rebuilding the xml file. Maybe somebody has an idea where and how this re-building could be controlled? Or is it the other way around and the uid originates from somewhere else? It isn't the permission on the APK in /data/app, that's always system:system.

I've also tried starting the APK via "am" hoping that it might inherit the shell uid... it was a desperate attempt and it turned out exactly like anybody would have expected: it didn't work.

The next thing was changing the permission on the process while it's running. On some Linux flavors root can change the permissions in /proc/* , but apparently not on Android.

Then I tried to use ActivityManagerNative::broadcastIntent instead of Content::sendIntent, but the check is buried too deep (as I said before): in order to get past the check I would need access to ActivityManagerService::sendPackageBroadcastLocked , but the object I get through IActivityManager::getDefault is actually only a proxy (ActivityManagerProxy) that forwards the public commands via an IBinder. Naturally the proxy doesn't have the private methods (private methods can still be called, but the proxy is a pretty good isolation layer).

The only thing that I can still think of would be implementing sendPackageBroadcastLocked myself.. it really only depends on the threads, which might be accessible... somehow

for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--)
mLruProcesses.get(i).thread.dispatchPackageBroadcast(cmd, packages);

These are IApplicationThread objects... they are not implemented in Java... at least the file contains only the prototypes. Is there some way to interact with such objects directly from the shell?

I would be really grateful if anybody had any idea... I just refuse to believe that I'm the first person to need root access rights beyond the shell.