Okay, I'll give them a try when I get home.
 
Just to clarify though, the current intent of the software is that the BOINC 
client only runs when the UI us running in some form.
 
It sounds like option A will break that design constraint.
 
----- Rom

________________________________

From: Joachim Fritzsch [mailto:[email protected]]
Sent: Sat 2/16/2013 3:39 AM
To: Rom Walton
Cc: BOINC Developers Mailing List
Subject: Re: Android Transition Portrait/Landscape mode


I think I found it. 

Apparently, a orientation change causes the main activity (BOINCActivity, tab 
host) to be destroyed (onPause, onDestroy) and re-created (onCreate, onResume). 
I was not aware that an orientation change causes this of behavior, but I guess 
it makes sense if there were two completely different layouts for each 
orientation.

With the main activity being destroyed, there is nothing bound to the service 
anymore, and it gets destroyed, too.

There are two ways to prevent this:

a) startService instead of bindService in BOINCActivity. With the service 
returning START_STICKY. This causes the service to stay around, even when there 
are no more activities.

b) adding android:configChanges="keyboardHidden|orientation" to the 
BOINCActivity's section in the Manifest, to prevent it being destroyed 
automatically in case of an orientation change.





On Sat, Feb 16, 2013 at 6:00 AM, Rom Walton <[email protected]> wrote:


        Wouldn't that have prevented the initial connection?
         
        ----- Rom

________________________________

        
        From: Joachim Fritzsch [mailto:[email protected]]
        
        Sent: Fri 2/15/2013 1:55 PM 

        To: Rom Walton
        Cc: BOINC Developers Mailing List
        
        Subject: Re: Android Transition Portrait/Landscape mode
        
        



        On Fri, Feb 15, 2013 at 4:09 PM, Rom Walton <[email protected]> wrote:
        

                Joachim,

                 

                It appears that the service monitor it being restarted when I 
switch my tablet from portrait mode to landscape mode.  Sometime after that 
network communication fails and things get stuck in a loop.

                 

                Shouldn't the service clean-up/abort its background threads 
when it is restarted?

                 

                ----- Rom

                 

                Logcat out of the transition:

                02-15 09:51:33.519: D/ClientMonitorAsync-doInBackground(3057): 
monitor loop...

                02-15 09:51:33.549: D/ClientStatus(3057): parsing results: 
computing: false30 - network: false20

                02-15 09:51:33.559: 
D/StatusActivity-localClientStatusRecNoisy(3057): received action 
edu.berkeley.boinc.clientstatuschange

                02-15 09:51:33.559: D/MainActivity-clientstatuschange(3057): 
received

                02-15 09:51:33.559: D/MainActivity(3057): determineStatus() old 
clientSetupStatus: 1 - newStatus: 1

                02-15 09:51:36.219: I/InputReader(479): Reconfiguring input 
devices.  changes=0x00000004

                02-15 09:51:36.229: I/InputReader(479): Device reconfigured: 
id=2, name='elan-touchscreen', size 800x1280, orientation 1, mode 1, display id 0

                02-15 09:51:36.229: I/ActivityManager(479): Config changes=1480 
{1.0 310mcc?mnc en_US ldltr sw600dp w961dp h528dp 213dpi lrg land finger 
-keyb/v/h -nav/h s.6}

                02-15 09:51:36.279: D/MainActivity(3057): onPause

                02-15 09:51:36.279: D/StatusActivity-onPause(3057): remove 
receiver

                02-15 09:51:36.299: D/MainActivity(3057): onDestroy

                02-15 09:51:36.309: D/dalvikvm(3057): GC_CONCURRENT freed 400K, 
8% free 7958K/8572K, paused 7ms+5ms, total 42ms

                02-15 09:51:36.379: D/MainActivity(3057): onCreate

                02-15 09:51:36.459: D/MainActivity(3057): tab layout setup done

                02-15 09:51:36.469: D/MainActivity(3057): onResume

                02-15 09:51:36.469: D/StatusActivity-onResume(3057): register 
receiver

                02-15 09:51:36.479: D/BOINC Client Monitor Service(3057): 
onDestroy()

                02-15 09:51:36.479: D/ShutdownClientAsync(3057): doInBackground

                02-15 09:51:36.519: D/dalvikvm(3057): GC_FOR_ALLOC freed 154K, 
6% free 8124K/8572K, paused 18ms, total 18ms

                02-15 09:51:36.589: D/dalvikvm(3057): GC_FOR_ALLOC freed 46K, 
6% free 8144K/8608K, paused 28ms, total 28ms

                02-15 09:51:36.589: I/dalvikvm-heap(3057): Grow heap (frag 
case) to 8.324MB for 262160-byte allocation

                02-15 09:51:36.609: D/dalvikvm(3057): GC_FOR_ALLOC freed 196K, 
8% free 8204K/8868K, paused 26ms, total 26ms

                02-15 09:51:36.609: D/BOINC Client Monitor Service(3057): 
onCreate()

                02-15 09:51:36.609: D/AppPreferences(3057): appPrefs read 
successful.false

                02-15 09:51:36.619: D/BOINC Client Monitor Service(3057): 
asynchronous monitor started!

                02-15 09:51:36.619: D/ClientMonitorAsync-doInBackground(3057): 
monitor loop...

                 

                Network communicaton failure:

                02-15 09:51:39.659: D/ClientSetupAsync-onProgressUpdate(3057): 
connect client.

                02-15 09:51:39.669: W/RpcClient(3057): connect failure

                02-15 09:51:39.669: W/RpcClient(3057): 
java.net.ConnectException: failed to connect to /127.0.0.1 <http://127.0.0.1/>  
(port 31416) after 30000ms: isConnected failed: ECONNREFUSED (Connection 
refused)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
libcore.io.IoBridge.isConnected(IoBridge.java:224)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
libcore.io.IoBridge.connectErrno(IoBridge.java:161)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
libcore.io.IoBridge.connect(IoBridge.java:112)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
java.net.Socket.connect(Socket.java:842)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
edu.berkeley.boinc.rpc.RpcClient.open(RpcClient.java:172)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
edu.berkeley.boinc.client.Monitor$ClientSetupAsync.connect(Monitor.java:699)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
edu.berkeley.boinc.client.Monitor$ClientSetupAsync.connectClient(Monitor.java:557)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
edu.berkeley.boinc.client.Monitor$ClientSetupAsync.startUp(Monitor.java:540)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
edu.berkeley.boinc.client.Monitor$ClientSetupAsync.doInBackground(Monitor.java:473)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
edu.berkeley.boinc.client.Monitor$ClientSetupAsync.doInBackground(Monitor.java:1)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
android.os.AsyncTask$2.call(AsyncTask.java:287)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
java.util.concurrent.FutureTask.run(FutureTask.java:234)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
java.lang.Thread.run(Thread.java:856)

                02-15 09:51:39.669: W/RpcClient(3057): Caused by: 
libcore.io.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)

                02-15 09:51:39.669: W/RpcClient(3057):                 at 
libcore.io.IoBridge.isConnected(IoBridge.java:208)

                02-15 09:51:39.669: W/RpcClient(3057):                 ... 16 
more


        This exception seems weird.

        Does this make sense?

        
http://stackoverflow.com/questions/10220905/application-force-closes-on-startup
        

         

                

                02-15 09:51:39.669: D/ClientSetupAsync-onProgressUpdate(3057): 
socket connection failed!

                 

                From: Joachim Fritzsch [mailto:[email protected]] 
                Sent: Friday, February 15, 2013 4:16 AM
                To: Rom Walton
                Cc: BOINC Developers Mailing List
                Subject: Re: BOINC Daemon Lifecycle on Android

                 

                Hi Rom,

                 

                I am impressed by the progress being made during the past week, 
keep it up!

                 

                On Fri, Feb 15, 2013 at 4:24 AM, Rom Walton <[email protected]> 
wrote:

                Joachim, et al.,

                 

                I have stumbled across some issues with starting up the BOINC 
daemon on Android and I needed to get some clarification on the various ways 
Android starts and stops activities and how that relates to the BOINC daemon.

                 

                My original problem occurred after installing a new version of 
the BOINC APK via adb.  I use the following command:

                $ adb install -r boinc_7.1.0_arm-android-linux-gnu.apk

                 

                This in turn caused Android to end the edu.berkeley.boinc 
process, which was expected.  Now when I started the BOINC UI, it was sending a 
SIGKILL to the daemon so it could update the daemon and re-launch it.

                 

                At this point things started to go sideways in that the new 
BOINC was attempting to re-launch the science applications, while the old ones 
were still executing.  While BOINC was trying to figure out what to do next, 
the UI had a connection failure event and would begin the cycle all over again. 
 At one point there were 12 wrapper applications executing and four science 
applications.

                I see. I have missed the science applications in this 
consideration... 

                 

                         

                        I committed 54df9353c689434b8bbb4d8b4f816a5f7733a095 
which resolves that specific issue by sending the BOINC daemon a SIGQUIT signal 
which allows it to shutdown and clean itself up and it's child processes.  It 
then waits for up to 15 seconds for /data/data/edu.berkeley.boinc/client/boinc 
to disappear off the process list.  If the BOINC daemon hasn't gracefully 
shutdown by then, it sends a SIGKILL.

                I don't have a chance to look into your commit right now, but 
are you doing this at 
edu.berkeley.boinc.client.Monitor.ClientSetupAsync.startUp() ? That's where the 
SIGKILL happens...

                         

                        Now I've run into an issue where the UI gets stuck in a 
similar cascade switching between portrait and landscape modes.

                This is odd. UI events should not have an effect on the deamon 
(except for the initial launch of course). The deamon is handled by the Android 
Service "edu.berkeley.boinc.client.Monitor".

                 

                         

                        So my question is, what is the desirable outcome for 
these startup situations:

                        1.       Launching the UI from the apps screen, when 
the daemon is not running?

                start daemon. (precisely, UI starts Service 
"edu.berkeley.boinc.client.Monitor" which verifies that there is no daemon 
running and starts it)

                This case also covers launch after boot.

                        2.       Launching the UI from the apps screen, when 
the daemon is running? (This seems to cover launching at boot, manual upgrades, 
automatic upgrades, and whenever Android decides to end various activities.)

                that's the really tricky one. A few points to keep in mind:

                a) boot is covered by 1.

                b) the daemon is launched by the Service, so ending and 
starting Activities should not influence it.

                c) The deamon is not subject to either removing the app from 
the task list nor OOM, not even de-installing the entire application. I could 
not come up with a way to close the daemon in those cases (see 5.)

                d) In case of an update, we need to stop the old deamon and 
start it from the new binaries.

                 

                Currently, it stops the deamon here in every case and re-starts 
it.

                 

                If it is possible to detect whether there has been an update to 
the binaries, the re-start could be conditional.

                 

                        3.       Switching to the UI from the apps screen?

                Should not effect the deamon, only creation of UI (implying 
creation of Service "Monitor")

                        4.       Switching between Landscape and Portrait modes?

                Should not effect the deamon at all. 

                        5.       Should removing the UI from the task list 
shutdown the daemon?

                Originally, I wanted to close the daemon here. We wouldn't have 
this mess if that would work. But unfortunately, neither closing (killing) the 
UI from task list nor by OOM seems to not be calling any life cycle methods 
(like onStop - onDestroy) one would expect! So, AFAIK, closing the daemon here 
is not possible. If anybody comes up with a way how to do that would improve 
the current implementation a lot!

                         

                        6.       Can we detect if/when Android has killed the 
daemon or any of its children because of the OOM driver? Should we find a way 
to have the daemon reschedule for execution later? 
(http://www.lindusembedded.com/blog/2010/12/07/android-linux-kernel-additions/)

                I don't think there is, correct me, if I am wrong. 

                         

                        Did I miss any other conditions?

                         

                        Thoughts?

                Bottom line, the root of the problem is the behavior of Android 
described in 5. - the daemon does not get stopped when the app gets killed by 
either OOM or by user through task list. 

                         

                        ----- Rom

                         

                 



_______________________________________________
boinc_dev mailing list
[email protected]
http://lists.ssl.berkeley.edu/mailman/listinfo/boinc_dev
To unsubscribe, visit the above URL and
(near bottom of page) enter your email address.

Reply via email to