Android process importance with a started service

2019-07-18 18:38发布

问题:

I'm trying to better understand process priorities in android especially when there is a service running in the same process where activities lives.

Android documentation explains that when there is a service started and the application goes in background the process will be a "Service process" with a higher rank in respect of a normal background process.

http://developer.android.com/guide/components/processes-and-threads.html

Process Lifecycle

3. Service process
A process that is running a service that has been started with the startService() method and does not fall into either of the two higher categories. Although service processes are not directly tied to anything the user sees, they are generally doing things that the user cares about (such as playing music in the background or downloading data on the network), so the system keeps them running unless there's not enough memory to retain them along with all foreground and visible processes.

...

Because a process running a service is ranked higher than a process with background activities, an activity that initiates a long-running operation might do well to start a service for that operation, rather than simply create a worker thread—particularly if the operation will likely outlast the activity.

http://developer.android.com/reference/android/app/Service.html

  • If the service has been started, then its hosting process is considered to be less important than any processes that are currently visible to the user on-screen, but more important than any process not visible. Because only a few processes are generally visible to the user, this means that the service should not be killed except in extreme low memory conditions.

To ensure this i have done a simple test, inside an app i have started a local internal service with startService and put the app in background while printing once a second ActivityManager.RunningAppProcessInfo.

I was expecting that the importance of the process will become IMPORTANCE_SERVICE but instead i get IMPORTANCE_BACKGROUND.

Why this happens?
Is the documentation wrong?
Even if i get IMPORTANCE_BACKGROUND the process is in any case more important than the others in background and so is still preferable using a local service?

EDIT: Here is an example code

Manifest declaration:

<service android:name=".EmptyService" android:exported="false" />

Service:

public class EmptyService extends Service {

    private static final String TAG = "EmptyService";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // empty service that is never stopped
        return START_NOT_STICKY;
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

Activity:

public class MyActivity extends Activity {

    private static final String TAG = "MyActivity";

    private final Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        startService(new Intent(this, EmptyService.class));
        mImportanceLogger.run();
    }

    private final Runnable mImportanceLogger = new Runnable() {
        @Override
        public void run() {
            final ActivityManager am = (ActivityManager) MyActivity.this.getSystemService(ACTIVITY_SERVICE);
            final List l = am.getRunningAppProcesses();
            final Iterator i = l.iterator();
            while(i.hasNext()) {
                final ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo)(i.next());
                if (info.processName.contains("serviceimportance")) {
                    // importance is 100 (IMPORTANCE_FOREGROUND) when the activity is visibile
                    // importance is 400 (IMPORTANCE_BACKGROUND) when the activity is in background
                    // but in the latter case i was expecting 300 (IMPORTANCE_SERVICE) because
                    // there is a service running
                    Log.i(TAG, info.processName + " importance " + info.importance + " importanceReason " + info.importanceReasonCode);
                }
            }

            mHandler.postDelayed(mImportanceLogger, 2000);
        }
    };
}

回答1:

I have played a bit with adb shell dumpsys activity p and found that the activity manager flags the process as cch-started-ui-services when there is a started service.
Furthermore you can understand that the app process has more priority than background processes without services by simply looking at the lru value (in dumpsys cch+1, cch+2 etc.) that is based first on processes that contains services and then on those that don't contains any started service.