Is there any reason why an Android device could start a new process of an app with the same name, same user ID and different PID, and keep the old one still alive?
The manifest doesn't specify any other processes other than the default one.
The old process can be killed through a kill command in a terminal.
Is that an expected behaviour in some defined cases or is it an Android bug?
The manifest looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mycompany.myapp"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="19" />
    <!-- omitted <uses-permission> tags -->
    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
        <!-- Start up -->
        <activity
            android:name=".activity.SplashScreenActivity"
            android:configChanges="orientation|keyboardHidden" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- other non-launcher activities... -->
        <!-- Auto start on boot -->
        <receiver android:name=".receiver.StartEventsReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <!-- Update content and configuration -->
        <receiver
            android:name=".receiver.UpdateContentReceiver"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.mycompany.myapp.UPDATE_CONTENT" />
                <action android:name="com.mycompany.myapp.CONTENT_UPDATED" />
            </intent-filter>
        </receiver>
        <!-- other receivers and services... -->
    </application>
</manifest>
UPDATE: I've managed to get some logging. My app has a Receiver called UpdateContentReceiver (manifest above updated) that is called every minute with an UPDATE_CONTENT intent, posted from the main message queue. It does some network polling and finishes. It used to work...
08-30 09:46:57.419  2512  2512 V UpdateContentReceiver: Received UPDATE_CONTENT
08-30 09:46:58.349  2512  2512 V UpdateContentReceiver: No update
08-30 09:47:57.439  2512  2512 V UpdateContentReceiver: Received UPDATE_CONTENT
08-30 09:47:57.739  2512  2512 V UpdateContentReceiver: No update
08-30 09:48:57.439  2512  2512 V UpdateContentReceiver: Received UPDATE_CONTENT
08-30 09:49:02.389  2512  2512 V UpdateContentReceiver: No update
... but the next time...
08-30 09:49:57.459  1879  1904 E JavaBinder: !!! FAILED BINDER TRANSACTION !!!
08-30 09:49:57.469  1879  1904 W BroadcastQueue: Exception when sending broadcast to ComponentInfo{com.mycompany.myapp/com.mycompany.myapp.receiver.UpdateContentReceiver}
08-30 09:49:57.469  1879  1904 W BroadcastQueue: android.os.TransactionTooLargeException
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.os.BinderProxy.transact(Native Method)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.app.ApplicationThreadProxy.scheduleReceiver(ApplicationThreadNative.java:771)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.BroadcastQueue.processCurBroadcastLocked(BroadcastQueue.java:231)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:778)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.BroadcastQueue$1.handleMessage(BroadcastQueue.java:140)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.os.Handler.dispatchMessage(Handler.java:99)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.os.Looper.loop(Looper.java:137)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.ActivityManagerService$AThread.run(ActivityManagerService.java:1487)
08-30 09:49:57.469  1879  1904 W ActivityManagerService: Scheduling restart of crashed service com.mycompany.myapp/.service.ServiceFoo in 5000ms
08-30 09:49:57.469  1879  1904 W ActivityManagerService: Scheduling restart of crashed service com.mycompany.myapp/.service.ServiceBar in 14999ms
08-30 09:49:57.469  1879  1904 W ActivityManagerServiceActivityStack_hong: Force removing ActivityRecord{42768bf8 u0 com.mycompany.myapp/.activity.MyActivity}: app died, no saved state
08-30 09:49:57.529  1879  1904 I ActivityManagerService: Start proc com.mycompany.myapp for broadcast com.mycompany.myapp/.receiver.UpdateContentReceiver: pid=27119 uid=10044 gids={50044, 3003, 1028, 1015, 1023}
The last line clearly says that a new process is created. After that, I see in the logs that MyApplication is started three times with different PIDs, until it settles with the last process living. Here's the ps|grep myapp output:
u0_a44    2512  1286  755540 85548 ffffffff 4003fee4 S com.mycompany.myapp                                                                      
u0_a44    28541 1286  772220 79204 ffffffff 4003fee4 S com.mycompany.myapp
I can't say why the TransactionTooLargeException happens (we only send UPDATE_CONTENT with no extras, so there's little memory footprint), but at least I know why a new process is created. Still it's unclear why the old process is not destroyed. The app has an internal web server: maybe Android sees that listening for a TCP port and refuses to kill it?
The funny thing is that the new process fails to run its own web server (because the listening port is already bound), but everything "works" because the old web server is still alive!
 
     
    