Usage of Android:Process

Implication of android:process when defining services or receivers

will this have an impact on the behaviour of the receiver and SyncService?

Not directly.

Can this impact the applications' behaviour when running

Thread safety becomes a bit more of an issue with everything in one process. OTOH, that can be a lot easier than coordinating work in 2+ processes such that one process does not stomp on the work of the other process.

I am aware than a service will be run on the main thread

The lifecycle methods of a service (e.g., onStartCommand()) will run on the main application thread; your business logic should run on background threads. You have to do that regardless of whether everything is in one process or split between processes.

will something stall or only delay when code is scheduled to run on the main thread?

If your service runs code on the main application thread, it will block everything else on that thread while that code runs. That is why services always use background threads.

Depending on how you are synchronizing access to shared objects, service code running on a background thread could lock access to those shared objects and therefore stall UI code that tries accessing those objects. That's why we try to organize our code to avoid blocking calls from the UI on such objects, such as by using reactive options (LiveData, RxJava, etc.).

Every Activity in Android is a Process,or One Application is one process

All activities inside an application run in one process?

It depends on value of android:process attribute in application manifest.

if attribute android:process is not defined for Application/Activity tags in the manifest, by default all the activities will run in single process (process name will be name of the package defined in manifest)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.so.test" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Activity1">
</activity>
<activity android:name=".Activity2">
</activity>
<activity android:name=".Activity3">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

In the above manifest all activities run in process com.so.test,ps command output in adb shell:

# ps
app_39 668 33 84492 20672 ffffffff afd0c51c S com.so.test

If android:process is specified for Activity new process will be created with the same userid and the activity runs in that process.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.so.test" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />

<application android:icon="@drawable/icon" android:label="@string/app_name"
android:process="com.so.p1">
<activity android:name=".Activity1">
</activity>
<activity android:name=".Activity2" android:process="com.so.p2">
</activity>
<activity android:name=".Activity3" android:process="com.so.p3">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

If the manifest is defined like above

Activity1 runs in com.so.p1 process
Activity2 runs in com.so.p2 process
Activity3 runs in com.so.p3 process

ps output in adb shell

# ps
app_39 650 33 83192 20900 ffffffff afd0c51c S com.so.p1
app_39 659 33 83188 20864 ffffffff afd0c51c S com.so.p2
app_39 668 33 84492 20672 ffffffff afd0c51c S com.so.p3

If an Activity needs to be run in another process not defined in this manifest, both APKs should be signed with the same certificate.

Start a service in a separate process android

Check out the process attribute for service in AndroidManifest.xml. You need to change your android:process value to start with a :.

http://developer.android.com/guide/topics/manifest/service-element.html

The relevant section:

If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.

The other answer provided doesn't really answer the question of how to start a service in a separate process.


Defining a Process of a Service

The android:process field defines the name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. However, a component can override the default with its own process attribute, allowing you to spread your application across multiple processes.

If the name assigned to this attribute begins with a colon (':'), the service will run in its own separate process.

<service
android:name="com.example.appName"
android:process=":externalProcess" />

If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.

android:process and process name

And what happens if I mix the two rules?

That's not possible. A colon is not a capital letter.

I need to have two components from two packages run in the same process to save resources (and to avoid having two "running apps" listed in the apps manager).

That's really not a good idea. Put them in the same package, or have them run independently.

Not only would you have to mess around with android:process, but you also have to mess around with android:sharedUserId. Neither of these are meant to be used by ordinary SDK developers, particularly android:sharedUserId. In fact, if you have already distributed your application, you can't use android:sharedUserId unless you're willing to break all your existing users' apps, since you will no longer be able to access your original data, since it'll be owned by some other user account.

Furthermore, unless you have evidence to the contrary, I would not assume that this will somehow "avoid having two 'running apps' listed in the apps manager".

Now, I am all for efficiency, and so creating extra processes for grins (e.g., misguided advice to make "remote services" run in custom processes) is a bad idea. And if you work for a device manufacturer or a firm with 20+ Android developers or something, and you want to mess around with this, you're going to need to find places where it is used in the AOSP and reverse-engineer the information you seek, since this stuff is seriously under-documented. And even there, I am not seeing it used between multiple packages, except for android.process.acore and com.android.phone, which are seriously low-level processes and are not going to be typical of non-firmware apps.

Hence, I really recommend that you leave these things alone.

processes & singleton in Android

  1. Does it mean there will be two JVM instances , one used by MyService while the other one used by other code?

yes (in a certain way, but not exactly, it's a dalvik VM, or in Lollipop ART), but yeah, you have two separate things running the service and rest of code.


  1. If the answer of above question is YES, then does it also mean if I have a singleton class used by both Activity & MyService, then there
    will be two instances created for the singleton?

yes


  1. How to ensure only one instance be created & shared by two processes then? Better provide a sample :)

you can't! You just told the system to have separate processes. So it cannot have "the same" singleton.

An approach to that is have your service implement a binder or AIDL (in case you to direct calls methods) or implement a ContentProvider, which is the same across processes that you can read values out of it.

Or you can just make it all simpler and NOT use the process. 99.9% of use cases android:process is not advised. So re-evaluate your software. Do you really need it?

edit:

unfortunately, my project need to use separate service process as it
has long running background tasks

If your project need a long running background task, you need a Service for sure. But it doesn't mean it needs to be in a separate process. All the activities from your project can go to background and be garbage collected and your service still runs fine. It will keep running on the same process as the Activities were running but the Service and singletons will still be alive. Just remember to return START_STICKY from it.

If you still think you need to use it in a separate process (I don't think you need). Then you need to implement a bound service (or maybe AIDL, I'm not sure bound service will work across process), connect the activity to it and give the reference of the object using a normal method like public void takeThisObJect(Object reference);

links to bound and AIDL service guides:

http://developer.android.com/guide/components/bound-services.html
http://developer.android.com/guide/components/aidl.html

how to get memory usage and cpu usage by application?

Context context = this.getApplicationContext();
ActivityManager mgr = (ActivityManager)context.getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses();
Log.e("DEBUG", "Running processes:");
for(Iterator i = processes.iterator(); i.hasNext(); )
{
RunningAppProcessInfo p = (RunningAppProcessInfo)i.next();
Log.e("DEBUG", " process name: "+p.processName);
Log.e("DEBUG", " pid: "+p.pid);
int[] pids = new int[1];
pids[0] = p.pid;
android.os.Debug.MemoryInfo[] MI = mgr.getProcessMemoryInfo(pids);
Log.e("memory"," dalvik private: " + MI[0].dalvikPrivateDirty);
Log.e("memory"," dalvik shared: " + MI[0].dalvikSharedDirty);
Log.e("memory"," dalvik pss: " + MI[0].dalvikPss);
Log.e("memory"," native private: " + MI[0].nativePrivateDirty);
Log.e("memory"," native shared: " + MI[0].nativeSharedDirty);
Log.e("memory"," native pss: " + MI[0].nativePss);
Log.e("memory"," other private: " + MI[0].otherPrivateDirty);
Log.e("memory"," other shared: " + MI[0].otherSharedDirty);
Log.e("memory"," other pss: " + MI[0].otherPss);

Log.e("memory"," total private dirty memory (KB): " + MI[0].getTotalPrivateDirty());
Log.e("memory"," total shared (KB): " + MI[0].getTotalSharedDirty());
Log.e("memory"," total pss: " + MI[0].getTotalPss());
}
  • In modern OS, app use shared libraries. Hence, some memory is used
    by multiple apps, complicating determining an apps memory usage.

  • dalvikPrivateDirty is the memory that would be freed by the java

    virtual machine if the process is killed

  • nativePrivateDirty is the same for native code is the same for some
    other code (not sure what else there is)
  • otherPrivateDirty dalvikSharedDirty is the shared memory used by the
    java virtual machine But this would not be freed

  • if this app is killed dalvikPss – an estimate of how much memory is

    used by the app. This includes all the private memory, and a

    fraction of the shared memory Check that pss >= private The reason

    that only a fraction of shared memory is used is so that

    reasonability of the shared memory usage across all responsible apps

This value is used to estimate the memory load of the app.

The totals are the sum over the dalvik, native, and other.



Related Topics



Leave a reply



Submit