Android input delay and crash

Monkey Targets Forums/Android/Android input delay and crash

nullterm(Posted 2016) [#1]
So I've been dealing with an issue with slower devices. When render/update is intense and taking longer than the device can keep up with, the GLThread has been causing the main thread to stall, so input gets delayed several seconds, and eventually the Android OS gets impatient and just kills my monkey app.

After some digging and monkeying around with the target .java code, I came to a solution which addresses most of the issue. Needs some cleanup though and better handling of app switching from foreground-background-foreground, but thought I'd post this first step if it helps others. Still working on a more robust solution.

Basically...
1. set the GLSurfaceView render mode to "when dirty" instead of continuous
2. post a runnable on the main thread that will request the view to be dirty and render

So the main and GLThread aren't fighting over the CPU and stalling the main.

	//***** GLSurfaceView.Renderer *****

	Runnable dirtyHandler = new Runnable() {
		@Override
		public void run() {
			if( !_canRender ) return;
			//System.out.println( "dirtyHandler requestRender on " + Thread.currentThread() );
	       		_view.requestRender();
		}
	};

	public void onDrawFrame( GL10 gl ){
		if( !_canRender ) return;
		
		StartGame();
	
		if( _updateRate==0 ){
			UpdateGame();
			RenderGame();

		// BMH HACK STARTS HERE
		if ( true ) {
			//System.out.println( "RENDERMODE_WHEN_DIRTY" );
			_view.setRenderMode( GLSurfaceView.RENDERMODE_WHEN_DIRTY );
			_activity.runOnUiThread(dirtyHandler);
		}
		// BMH HACK ENDS HERE

			return;
		}
			
...



nullterm(Posted 2016) [#2]
Based on further testing, the foreground-background-foreground crash isn't related to my "dirty" change. It's based on some Monkey side OpenGL I wrote for rendering, guessing Android is flushing everything and I need to restore all the vertex buffer and texture data back to the GPU.

Edit - solved my GLES2 resource issue by reloading vertex buffer, shader, texture data and everything works great. Now my Samsung Tab3 doesn't crash and responds correctly to touch events.


Leginus(Posted 2016) [#3]
Thanks for posting a followup


Simonsuuri(Posted 2016) [#4]
i have problem with my android game that when it loads and draw images at first time (I suppose) it does freeze for a second here and there,
and i splitted my loading with menu stuff and game stuff just to make loading times shorter...

i wonder if this could be some sort of solution for freeze moments...?

also actually i wonder if images Pixels per Inch value or someting similiar, does make a difference? since basicly i think that freeze is not same length on some images as other (even if they are same size)?

and third what i have been thinking is that should i use GrabImage in loading, to make images of game objects smaller?


Phil7(Posted 2016) [#5]
@Simonsuuri
I had the same problem, but it had nothing to do with this post as far as I know. Android seems to copy the images in the gfx memory the first time it is rendered not when it is loaded. My solution was to render all the images once after loading. You can avoid showing it to the user by drawing it offscreen or with setalpha(0.0)(but you have to test it yourself ;-) ).
The freeze/copy time depends on the size of memory it needs, so an image with higher resolution takes longer to load.
As far as I know it doesn't make a difference if you use grabimage with a spritesheets. Here the copy freeze happened the first time I rendered a peace of your sheet.


Simonsuuri(Posted 2016) [#6]
hmm... ok.. is there any way to push prosessing of the image handling (when data is being sent to GPU) to background thread so that it would at least keep mobile to be responsive..?

and um.. i wonder... My main Image files are Global atm. would that help if i set them to be fields/local to Game Class?


Phil7(Posted 2016) [#7]
I don't think it makes a difference where you have the image variables.
Do you have a loading scene when starting your app? I would keep the images global and load them at this time and then display them just after that.
Can you explain why you don't want to do it like that?
Btw. I don't know if a thread would solve that problem, sorry.


Simonsuuri(Posted 2016) [#8]
thanks, well im trying to avoid a situation that i would need to split my game images physically smaller, since it would take so much work and code. :)

l Actually have a loading system that load images and then draw to gpu, it takes a laggy moments out from game itself but sometimes some images are deleted from memory so if game creates enemy that has that image game freezes for 1/2 -1 second.
And im trying to understand the reason why mobiles do that / how to handle it etc.
and today i realized that threading is indeed not a reason nor answer because freeze comes with writing stuff to gpu.

I think my plan for my game at next week is

1. To try if image variables in game/app class are handled differently, (easy to try)
2. To try if drawing image in rects to gpu is making differece / possible (propably not)
3. To try if using grabimage to make smaller images for assets helps with freezes (propably not in loading tho, but InGame freezes should ease)
4. cry, and split all images smaller and load them to earlier made grabimage variables.


Phil7(Posted 2016) [#9]
So you have the problem, that you have to many different enemies with to much memory usage, therefore you cannot load them all before the game starts and you want to keep on loading them during the game.action. In this case I don't have a clue, but would also be very interested, if you come up with a solution. :-)

Another solution might be to use larger (but within 1024x1024 for android) spitesheets. (just guessing you don't, because you wrote about loading each enemy separately.) This could save some memory and make the loading and first drawing easier to handle.

Please keep up your investigation! ;-)


Simonsuuri(Posted 2016) [#10]
Allright, I studied more about android limitation stuff during a weekend.. And desided to go bigger than smaller, and it seems to work..
My phone is Samsung Trend Plus so it's quite good for testing since it's not too fast, and it took 32 seconds to load my game with long freeze times...
Anyways I joined my game images and sized them to use more or less "power of two" resolutions..

With menu images I joined 3 backgroundimages 640*1136 to 2 1024*1024 sized images and 2 loadingscreens I made 640*1136 to 512*1024,
I also joined some minor images with my buttonimages..
And InGame images I chanced 6 background images from 1136*1136 to 1024*1024 and joined 4 Enemy images to 2 Enemy images.. Frame sizes was about 192*192 and 288*192
and so... Also I tried to save those files a bit smaller, with less colors..

And after that the loading time in "stress test" load(loaded all images at game start) time redused from 32sec to 22sec

After that I optimized loading system by splitting stuff for menuLoad and gameLoad and made each 10th-tick to draw 1 image to GPU,
And now the loading time with my phone is around 10 seconds to menu and another 10 seconds to play (at first time).. So I am quite happy for now...

Also I found out the reason why android forgot some images, and that was because I was trying to draw images to GPU too rapidly so it skipped some images..

There is still a bit long freeze(3-5seconds), when Sounds are loaded but I'll handlle that tomorrow.

Now after sound loading is done at early load my phone responds quite good for like chancing phone volume or close app commads.. :)
And I assume that since there is not that much different images in memory, the game takes less ram.

I will do more optimizing for loading/Image system, when my game is (soon) in "beta" testing. And I propably make SD/HD data system

Thanks for helping Phil07!