Skip to content

Commit de47c8a

Browse files
Merge pull request #394 from bugsnag/in-foreground-fixes
Fix calculation of durationInForeground when autoCaptureSessions is false
2 parents dca07c0 + 0de6d2a commit de47c8a

File tree

4 files changed

+70
-11
lines changed

4 files changed

+70
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.bugsnag.android.mazerunner.scenarios
2+
3+
import android.content.Context
4+
import com.bugsnag.android.Bugsnag
5+
import com.bugsnag.android.Configuration
6+
import java.lang.Thread
7+
import android.os.Handler
8+
import android.os.HandlerThread
9+
10+
/**
11+
* Sends a handled exception to Bugsnag, which has a short delay to allow the app to remain
12+
* in the foreground for ~1 second
13+
*/
14+
internal class InForegroundScenario(config: Configuration,
15+
context: Context) : Scenario(config, context) {
16+
init {
17+
config.setAutoCaptureSessions(false)
18+
}
19+
20+
override fun run() {
21+
super.run()
22+
23+
val thread = HandlerThread("HandlerThread")
24+
thread.start()
25+
Handler(thread.looper).post {
26+
Thread.sleep(5000)
27+
Bugsnag.notify(generateException())
28+
}
29+
30+
}
31+
32+
}

features/in_foreground.feature

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Feature: In foreground field populates correctly
2+
3+
Scenario: Test handled exception after delay
4+
When I run "InForegroundScenario"
5+
Then I should receive a request
6+
And the request is a valid for the error reporting API
7+
And the event "app.inForeground" is true
8+
9+
# Duration in foreground should be a non-zero integer
10+
And the payload field "events.0.app.durationInForeground" is greater than 0
11+
12+
Scenario: Test handled exception in background
13+
When I run "InForegroundScenario" and press the home button
14+
And I press the home button
15+
Then I should receive a request
16+
And the request is a valid for the error reporting API
17+
And the event "app.inForeground" is false
18+
And the payload field "events.0.app.durationInForeground" equals 0

features/steps/build_steps.rb

+5
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,8 @@
175175
assert_not_nil(frame['lineNumber'], "The lineNumber of frame #{index} is nil")
176176
end
177177
end
178+
179+
Then(/^the payload field "(.+)" is greater than (\d+)(?: for request (\d+))?$/) do |field_path, int_value, request_index|
180+
observed_value = read_key_path(find_request(request_index)[:body], field_path)
181+
assert(observed_value > int_value)
182+
end

sdk/src/main/java/com/bugsnag/android/SessionTracker.java

+15-11
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ class SessionTracker extends Observable implements Application.ActivityLifecycle
3636
private final SessionStore sessionStore;
3737

3838
// This most recent time an Activity was stopped.
39-
private AtomicLong activityLastStoppedAtMs = new AtomicLong(0);
39+
private AtomicLong lastExitedForegroundMs = new AtomicLong(0);
4040

4141
// The first Activity in this 'session' was started at this time.
42-
private AtomicLong activityFirstStartedAtMs = new AtomicLong(0);
42+
private AtomicLong lastEnteredForegroundMs = new AtomicLong(0);
4343
private AtomicReference<Session> currentSession = new AtomicReference<>();
4444
private Semaphore flushingRequest = new Semaphore(1);
4545

@@ -261,7 +261,7 @@ void startFirstSession(Activity activity) {
261261
Session session = currentSession.get();
262262
if (session == null) {
263263
long nowMs = System.currentTimeMillis();
264-
activityFirstStartedAtMs.set(nowMs);
264+
lastEnteredForegroundMs.set(nowMs);
265265
startNewSession(new Date(nowMs), client.getUser(), true);
266266
foregroundActivities.add(getActivityName(activity));
267267
}
@@ -282,20 +282,24 @@ void startFirstSession(Activity activity) {
282282
*/
283283
void updateForegroundTracker(String activityName, boolean activityStarting, long nowMs) {
284284
if (activityStarting) {
285-
long noActivityRunningForMs = nowMs - activityLastStoppedAtMs.get();
285+
long noActivityRunningForMs = nowMs - lastExitedForegroundMs.get();
286286

287287
//FUTURE:SM Race condition between isEmpty and put
288-
if (foregroundActivities.isEmpty()
289-
&& noActivityRunningForMs >= timeoutMs
290-
&& configuration.shouldAutoCaptureSessions()) {
288+
if (foregroundActivities.isEmpty()) {
289+
lastEnteredForegroundMs.set(nowMs);
291290

292-
activityFirstStartedAtMs.set(nowMs);
293-
startNewSession(new Date(nowMs), client.getUser(), true);
291+
if (noActivityRunningForMs >= timeoutMs
292+
&& configuration.shouldAutoCaptureSessions()) {
293+
startNewSession(new Date(nowMs), client.getUser(), true);
294+
}
294295
}
295296
foregroundActivities.add(activityName);
296297
} else {
297298
foregroundActivities.remove(activityName);
298-
activityLastStoppedAtMs.set(nowMs);
299+
300+
if (foregroundActivities.isEmpty()) {
301+
lastExitedForegroundMs.set(nowMs);
302+
}
299303
}
300304
setChanged();
301305
notifyObservers(new NativeInterface.Message(
@@ -310,7 +314,7 @@ boolean isInForeground() {
310314
//FUTURE:SM This shouldnt be here
311315
long getDurationInForegroundMs(long nowMs) {
312316
long durationMs = 0;
313-
long sessionStartTimeMs = activityFirstStartedAtMs.get();
317+
long sessionStartTimeMs = lastEnteredForegroundMs.get();
314318

315319
if (isInForeground() && sessionStartTimeMs != 0) {
316320
durationMs = nowMs - sessionStartTimeMs;

0 commit comments

Comments
 (0)