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!