I am working on a third-party library for Android and need to be able to tell if I am running as a privileged process with my desired permissions, or if I am living in an isolated process with restricted permissions as defined in the AndroidManifest.xml file:
<service android:name="mySandboxedService" android:permission="com.android.chrome.permission.CHILD_SERVICE" android:exported="false" android:process=":sandboxed_process0" android:isolatedProcess="true" />
The reason being that certain things I'm trying to do, such as get the number of running application processes (and various other things), will throw a RuntimeException if they are isolated. This code will run successfully if not run as an isolated process, but will throw RTE if the process is isolated:
ActivityManager aM = (ActivityManager) context.getSystemService(android.content.Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> l = null;
try {
l = aM.getRunningAppProcesses();
} catch (RuntimeException e) {
Log.w(LOGTAG, "Isolated process not allowed allowed to call getRunningAppProcesses, cannot get number of running apps.");
}
From my logcat:
java.lang.SecurityException: Isolated process not allowed to call getRunningAppProcesses
Does anyone know of a way I can check my current process to see if it is isolated or privileged? I've checked the Android Service doc here, and it does not provide much information.
My end goal is to initialize my app once from the main, privileged thread, and then ignore all of the startup calls from the various sandboxed processes that may get created. I don't want to run in those, but my hook is in Application.onCreate and gets called for every process, sandboxed or not.
I've considered the idea of adding one of these checks to my initialization and catching the RTE if it's thrown. But if there is a public API for it, I'd rather use that.
remember, android is linux: process = any running program. e.g. something with a PID. service = roughly equivalent to a daemon. something running in the background with no direct user interface.
android:isolatedProcess. If set to true, this service will run under a special process that is isolated from the rest of the system and has no permissions of its own. The only communication with it is through the Service API (binding and starting).
One can check the uid of the running process to see if they fall in the range of isolated process.
int AID_ISOLATED_START = 99000;
int AID_ISOLATED_END = 99999;
int uid = Process.myUid();
if (uid >= AID_ISOLATED_START && uid <= AID_ISOLATED_END) {
Log.i(TAG, "This is from an isolated process");
}
Process range info source: https://android.googlesource.com/platform/system/sepolicy/+/master/public/isolated_app.te
EDIT: The above has been found to be unreliable on Android 8.1 and below. Another approach is to try accessing privileged APIs and see if an exception is thrown.
try {
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
activityManager.getRunningAppProcesses();
} catch (SecurityException e) {
Log.i(TAG, "This is from an isolated process");
}
As pointed out in an other answer, Android Pie/9 (API 28) introduced a new API for this. See https://developer.android.com/reference/android/os/Process#isIsolated().
This seems to be present in versions as low as Android 4.3. See https://cs.android.com/android/platform/superproject/+/android-4.3.1_r1:frameworks/base/core/java/android/os/Process.java;l=680
API 28 (Android Pie / 9) introduced new method for checking if current process is an isolated one: Process#isIsolated.
Note that this method was added to Process class in API 16, but was hidden till API 28. Therefore the following method can be used to check if the process is isolated or not (this is actually how Chrome app performs this check):
@SuppressLint("NewApi")
public boolean isIsolated() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
return false;
}
return android.os.Process.isIsolated();
}
Checking if the UID is in the {99000, 99999} range (as demonstrated in the accepted answer) will produce incorrect results in multi-user/profile environment for all users/profiles which are not the main one - since their UIDs will be prefixed with matching user id (example UID for user 10's isolated process will be 1099013).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With