Skip to content

Commit ac219fa

Browse files
committed
fixes edge cases in Android Native App rendering
Squashed commit of the following: commit ba7271f Author: mgood7123 <[email protected]> Date: Sat Jul 3 03:12:45 2021 +1000 use std::atomic instead of std::mutex commit 54e3973 Author: mgood7123 <[email protected]> Date: Tue Jun 29 07:52:35 2021 +1000 fixes edge cases in Android Native App rendering Revert "fix possible rendering edge cases" This reverts commit 3d76fb8. fix possible rendering edge cases Update AndroidMain.cpp add functions for app status apply validator suggestions Update AndroidAppBase.hpp Update AndroidAppBase.cpp remove unused variables
1 parent 7ecb18d commit ac219fa

File tree

3 files changed

+163
-36
lines changed

3 files changed

+163
-36
lines changed

NativeApp/include/Android/AndroidAppBase.hpp

+31-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
#pragma once
2727

2828
#include <memory>
29+
#include <atomic>
2930

3031
#include <android_native_app_glue.h>
32+
#include "FlagEnum.h"
3133
#include "AppBase.hpp"
3234

3335
#include "NDKHelper.h"
@@ -52,6 +54,31 @@ class AndroidAppBase : public AppBase
5254
static int32_t HandleInput(android_app* app, AInputEvent* event);
5355
static void HandleCmd(android_app* app, int32_t cmd);
5456

57+
// Android lifecycle status flags. Not app-specific
58+
enum APP_STATUS_FLAGS
59+
{
60+
APP_STATUS_FLAG_NONE = 0x00000000,
61+
62+
// Set between onCreate and onDestroy
63+
APP_STATUS_FLAG_RUNNING = 0x00000001,
64+
65+
// Set between onResume and onPause
66+
APP_STATUS_FLAG_ACTIVE = 0x00000002,
67+
68+
// Set between onWindowFocusChanged(true) and (false)
69+
APP_STATUS_FLAG_FOCUSED = 0x00000004,
70+
71+
// Set when the app's SurfaceHolder points to a
72+
// valid, nonzero-sized surface
73+
APP_STATUS_FLAG_HAS_REAL_SURFACE = 0x00000008
74+
};
75+
76+
APP_STATUS_FLAGS GetAppStatus();
77+
void AddAppStatusFlag(APP_STATUS_FLAGS Flag);
78+
void RemoveAppStatusFlag(APP_STATUS_FLAGS Flag);
79+
bool ValueHasAppStatusFlag(APP_STATUS_FLAGS Value, APP_STATUS_FLAGS Flag);
80+
bool HasAppStatusFlag(APP_STATUS_FLAGS Flag);
81+
5582
protected:
5683
virtual void Initialize()
5784
{
@@ -89,11 +116,14 @@ class AndroidAppBase : public AppBase
89116
void UpdateFPS(float fFPS);
90117

91118
bool initialized_resources_ = false;
92-
bool has_focus_ = false;
119+
120+
std::atomic<APP_STATUS_FLAGS> app_status_{APP_STATUS_FLAG_NONE};
93121

94122
ASensorManager* sensor_manager_ = nullptr;
95123
const ASensor* accelerometer_sensor_ = nullptr;
96124
ASensorEventQueue* sensor_event_queue_ = nullptr;
97125
};
98126

127+
DEFINE_FLAG_ENUM_OPERATORS(AndroidAppBase::APP_STATUS_FLAGS)
128+
99129
} // namespace Diligent

NativeApp/src/Android/AndroidAppBase.cpp

+129-35
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525

2626
#include "AndroidAppBase.hpp"
27+
#include "Errors.hpp"
2728
#include "Timer.hpp"
2829

2930
#include <android/sensor.h>
@@ -118,22 +119,44 @@ void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd)
118119
AndroidAppBase* eng = (AndroidAppBase*)app->userData;
119120
switch (cmd)
120121
{
121-
case APP_CMD_SAVE_STATE:
122-
break;
123-
124122
case APP_CMD_INIT_WINDOW:
125-
// The window is being shown, get it ready.
126-
if (app->window != NULL)
123+
LOG_INFO_MESSAGE("APP_CMD_INIT_WINDOW");
124+
app->window = app->pendingWindow;
125+
if (app->window &&
126+
ANativeWindow_getWidth(app->window) &&
127+
ANativeWindow_getHeight(app->window))
127128
{
129+
LOG_INFO_MESSAGE("INIT DISPLAY - HAS SURFACE");
128130
eng->InitDisplay();
129131
eng->DrawFrame();
132+
eng->AddAppStatusFlag(APP_STATUS_FLAG_HAS_REAL_SURFACE);
133+
}
134+
else
135+
{
136+
LOG_INFO_MESSAGE("NO SURFACE");
137+
eng->RemoveAppStatusFlag(APP_STATUS_FLAG_HAS_REAL_SURFACE);
130138
}
131139
break;
132140

133-
case APP_CMD_CONFIG_CHANGED:
141+
case APP_CMD_TERM_WINDOW:
142+
LOG_INFO_MESSAGE("APP_CMD_TERM_WINDOW - LOST SURFACE - TERM DISPLAY");
143+
{
144+
eng->RemoveAppStatusFlag(APP_STATUS_FLAG_HAS_REAL_SURFACE);
145+
}
146+
eng->TermDisplay();
147+
break;
148+
149+
// Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never
150+
// generated by android_native_app_glue
151+
case APP_CMD_CONTENT_RECT_CHANGED:
134152
{
135-
// This callback is not reliable for handling orientation changes. Depending on the
136-
// device, it may be called before or after the surface has been actually resized.
153+
LOG_INFO_MESSAGE("APP_CMD_CONTENT_RECT_CHANGED");
154+
155+
int32_t new_window_width =
156+
app->contentRect.right - app->contentRect.left;
157+
int32_t new_window_height =
158+
app->contentRect.bottom - app->contentRect.top;
159+
eng->WindowResize(new_window_width, new_window_height);
137160
break;
138161
}
139162

@@ -144,45 +167,82 @@ void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd)
144167
// does not work either - the callback is only called once after the window has been created.
145168
case APP_CMD_WINDOW_RESIZED:
146169
{
147-
auto new_window_width = ANativeWindow_getWidth(app->window);
148-
auto new_window_height = ANativeWindow_getHeight(app->window);
149-
eng->WindowResize(new_window_width, new_window_height);
170+
LOG_INFO_MESSAGE("APP_CMD_WINDOW_RESIZED");
171+
if (app->window)
172+
{
173+
int32_t new_window_width = ANativeWindow_getWidth(app->window);
174+
int32_t new_window_height = ANativeWindow_getHeight(app->window);
175+
if (new_window_width && new_window_height)
176+
{
177+
eng->WindowResize(new_window_width, new_window_height);
178+
}
179+
}
150180
break;
151181
}
152182

153-
// Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never
154-
// generated by android_native_app_glue
155-
case APP_CMD_CONTENT_RECT_CHANGED:
156-
{
157-
auto new_window_width = app->contentRect.right - app->contentRect.left;
158-
auto new_window_height = app->contentRect.bottom - app->contentRect.top;
159-
eng->WindowResize(new_window_width, new_window_height);
183+
case APP_CMD_GAINED_FOCUS:
184+
LOG_INFO_MESSAGE("APP_CMD_GAINED_FOCUS - HAS FOCUS");
185+
{
186+
eng->AddAppStatusFlag(APP_STATUS_FLAG_FOCUSED);
187+
}
188+
eng->ResumeSensors();
189+
break;
190+
191+
case APP_CMD_LOST_FOCUS:
192+
LOG_INFO_MESSAGE("APP_CMD_LOST_FOCUS - LOST FOCUS");
193+
{
194+
eng->RemoveAppStatusFlag(APP_STATUS_FLAG_FOCUSED);
195+
}
196+
eng->SuspendSensors();
197+
break;
198+
199+
case APP_CMD_RESUME:
200+
LOG_INFO_MESSAGE("APP_CMD_RESUME - IS ACTIVE");
201+
{
202+
eng->AddAppStatusFlag(APP_STATUS_FLAG_ACTIVE);
203+
}
204+
break;
205+
206+
case APP_CMD_START:
207+
LOG_INFO_MESSAGE("APP_CMD_START");
160208
break;
161-
}
162209

163-
case APP_CMD_TERM_WINDOW:
164210
case APP_CMD_PAUSE:
165-
// The window is being hidden or closed, clean it up.
166-
eng->TermDisplay();
167-
eng->has_focus_ = false;
211+
LOG_INFO_MESSAGE("APP_CMD_PAUSE - IS NOT ACTIVE");
212+
{
213+
eng->RemoveAppStatusFlag(APP_STATUS_FLAG_ACTIVE);
214+
}
168215
break;
169216

170217
case APP_CMD_STOP:
218+
LOG_INFO_MESSAGE("APP_CMD_STOP");
171219
break;
172220

173-
case APP_CMD_GAINED_FOCUS:
174-
eng->ResumeSensors();
175-
//Start animation
176-
eng->has_focus_ = true;
221+
case APP_CMD_CONFIG_CHANGED:
222+
LOG_INFO_MESSAGE("APP_CMD_CONFIG_CHANGED");
223+
// AConfiguration_fromAssetManager(app->config, app->activity->assetManager);
224+
// This callback is not reliable for handling orientation changes. Depending on the
225+
// device, it may be called before or after the surface has been actually resized.
177226
break;
178227

179-
case APP_CMD_LOST_FOCUS:
180-
eng->SuspendSensors();
181-
// Also stop animating.
182-
eng->has_focus_ = false;
228+
case APP_CMD_DESTROY:
229+
LOG_INFO_MESSAGE("APP_CMD_DESTROY - IS NOT RUNNING");
230+
{
231+
eng->RemoveAppStatusFlag(APP_STATUS_FLAG_RUNNING);
232+
}
233+
break;
234+
235+
case APP_CMD_WINDOW_REDRAW_NEEDED:
236+
LOG_INFO_MESSAGE("APP_CMD_WINDOW_REDRAW_NEEDED");
237+
if (eng->IsReady()) eng->DrawFrame();
238+
break;
239+
240+
case APP_CMD_SAVE_STATE:
241+
LOG_INFO_MESSAGE("APP_CMD_SAVE_STATE");
183242
break;
184243

185244
case APP_CMD_LOW_MEMORY:
245+
LOG_INFO_MESSAGE("APP_CMD_LOW_MEMORY");
186246
//Free up GL resources
187247
eng->TrimMemory();
188248
break;
@@ -244,10 +304,11 @@ void AndroidAppBase::SetState(android_app* state, const char* native_activity_cl
244304

245305
bool AndroidAppBase::IsReady()
246306
{
247-
if (has_focus_)
248-
return true;
249-
250-
return false;
307+
APP_STATUS_FLAGS app_status = GetAppStatus();
308+
return ValueHasAppStatusFlag(app_status, APP_STATUS_FLAG_RUNNING) &&
309+
ValueHasAppStatusFlag(app_status, APP_STATUS_FLAG_ACTIVE) &&
310+
ValueHasAppStatusFlag(app_status, APP_STATUS_FLAG_FOCUSED) &&
311+
ValueHasAppStatusFlag(app_status, APP_STATUS_FLAG_HAS_REAL_SURFACE);
251312
}
252313

253314
//void Engine::TransformPosition( ndk_helper::Vec2& vec )
@@ -285,4 +346,37 @@ void AndroidAppBase::UpdateFPS(float fFPS)
285346
return;
286347
}
287348

349+
AndroidAppBase::APP_STATUS_FLAGS AndroidAppBase::GetAppStatus()
350+
{
351+
return app_status_.load();
352+
}
353+
354+
void AndroidAppBase::AddAppStatusFlag(AndroidAppBase::APP_STATUS_FLAGS Flag)
355+
{
356+
auto LastStoredValue = app_status_.load();
357+
while (!app_status_.compare_exchange_weak(LastStoredValue, static_cast<APP_STATUS_FLAGS>(LastStoredValue | Flag)))
358+
{
359+
// If exchange fails, LastStoredValue will hold the actual value of app_status_.
360+
}
361+
}
362+
363+
void AndroidAppBase::RemoveAppStatusFlag(AndroidAppBase::APP_STATUS_FLAGS Flag)
364+
{
365+
auto LastStoredValue = app_status_.load();
366+
while (!app_status_.compare_exchange_weak(LastStoredValue, static_cast<APP_STATUS_FLAGS>(LastStoredValue & ~Flag)))
367+
{
368+
// If exchange fails, LastStoredValue will hold the actual value of app_status_.
369+
}
370+
}
371+
372+
bool AndroidAppBase::ValueHasAppStatusFlag(AndroidAppBase::APP_STATUS_FLAGS Value, AndroidAppBase::APP_STATUS_FLAGS Flag)
373+
{
374+
return (Value & Flag) != APP_STATUS_FLAG_NONE;
375+
}
376+
377+
bool AndroidAppBase::HasAppStatusFlag(AndroidAppBase::APP_STATUS_FLAGS Flag)
378+
{
379+
return ValueHasAppStatusFlag(app_status_.load(), Flag);
380+
}
381+
288382
} // namespace Diligent

NativeApp/src/Android/AndroidMain.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ using namespace Diligent;
4242
void android_main(android_app* state)
4343
{
4444
std::unique_ptr<AndroidAppBase> theApp(CreateApplication());
45+
46+
theApp->AddAppStatusFlag(AndroidAppBase::APP_STATUS_FLAG_RUNNING);
47+
4548
theApp->SetState(state, NATIVEACTIVITY_CLASS_NAME);
4649

4750
//Init helper functions

0 commit comments

Comments
 (0)