title: Android app dies with "Launch timeout has expired, giving up wake lock!" on certain phones
body: <p>I am working on an Android app that displays a continuous custom-rendered animation on the title screen and thus doesn't really enter the idle state when it's done loading. On most devices I've tested, everything runs fine, but Samsung's Galaxy S2 kills the app after a few seconds. I don't get a stack trace or any output of the <a href="http://developer.android.com/reference/java/lang/System.html#out" rel="nofollow noreferrer">System.out</a> output that I put into the <a href="http://developer.android.com/reference/android/app/Activity.html#onPause()" rel="nofollow noreferrer">onPause</a> event handler and the <a href="http://developer.android.com/reference/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)" rel="nofollow noreferrer">default uncaught exception handler</a>, so it doesn't seem to be a normal exit or an Exception in my code.</p>
  
  <p>The only output I get in LogCat is the following:</p>
  
  <pre><code>Launch timeout has expired, giving up wake lock!
  Sending signal. PID: 22344 SIG: 3
  handleActivityTimeout pid=[22344] cnt=10
  Process ... (pid 22344) has died.
  </code></pre>
  
  <p>There are several related posts here on SO (<a href="https://stackoverflow.com/questions/14184018/android-launch-timeout-has-expired-giving-up-wake-lock">1</a>, <a href="https://stackoverflow.com/questions/7489376/warn-activitymanager78-launch-timeout-has-expired-giving-up-wake-lock-wh">2</a>, <a href="https://stackoverflow.com/questions/4283449/activity-idle-timeout-for-historyrecord">3</a>, <a href="https://stackoverflow.com/questions/10031624/launch-timeout-has-expired-giving-up-wake-lock-activity-idle-timeout-for-histo">4</a>), but they all seem to trigger the issue slightly differently (alarm, recursive loops, network requests in the UI thread, ...). The last one links to a <a href="https://groups.google.com/forum/?fromgroups#!topic/android-developers/TfkPlN5b-ig" rel="nofollow noreferrer">Google Groups discussion</a> that says that this error message can simply be ignored. An approach I'd rather not take since it causes my app to actually crash on the Galaxy S2 (and maybe others?).</p>
  
  <p>Basically what I did was to write a custom <a href="http://developer.android.com/reference/android/view/View.html" rel="nofollow noreferrer">View</a> that renders the next animation-frame in its <a href="http://developer.android.com/reference/android/view/View.html#onDraw(android.graphics.Canvas)" rel="nofollow noreferrer">onDraw()</a> method and then calls <a href="http://developer.android.com/reference/android/view/View.html#postInvalidate()" rel="nofollow noreferrer">postInvalidate()</a> right before returning from onDraw(). In case it matters: My first postInvalidate() call happens during <a href="http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle)" rel="nofollow noreferrer">onCreate(...)</a>.</p>
  
  <p>The rendering is very quick and runs at 40+ frames per second on that device and well over 60 fps on more modern phones. So control goes back to the event loop very frequently and the app is also very responsive. Yet, the Galaxy seems to think that it has crashed and kills it (if that is even the reason for my app dying there). The thing is: If I am quick enough to click on a menu-item in my app to end up on a screen without an animation to break out of the "tail-recursive" postInvalidate() once, everything runs fine. Even if I then go back to the title screen for a long time where the animation runs again.</p>
  
  <p>So, of course, I could probably just use <a href="http://developer.android.com/reference/android/view/View.html#postInvalidateDelayed(long)" rel="nofollow noreferrer">postInvalidateDelayed(...)</a> once to break out of the start-up check, but that seems like a bit of a hacky solution and I don't know if there might be any other devices out there that might consider my app dead at a later stage (not just during start-up) and kill it.</p>
  
  <p>Is there something fundamentally wrong with using postInvalidate() in the way I'm doing? Is there a way to fix it? I would like to avoid having to move to a separate thread since that opens a whole other can of worms as far as passing events back and forth between the UI and that thread. I know it wouldn't be the end of the world and using a <a href="http://developer.android.com/reference/android/view/SurfaceView.html" rel="nofollow noreferrer">SurfaceView</a>, it might even lead to a slight performance improvement, but it's really just not necessary from a user experience point of view (everything runs perfectly smooth), so I'd like to avoid the involved additional opportunities for issues (multi-threading is notoriously difficult to debug).</p>