summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicoleYarroch <nicole@livio.io>2020-04-08 13:14:36 -0400
committerNicoleYarroch <nicole@livio.io>2020-04-08 13:14:36 -0400
commit94e8660b1ff662b8739df92c0bccef5050139c98 (patch)
tree308312367b97784b35c192b74e12a0c795820167
parent264b6b4f13aeb42b07b9b4a6698c70da6310f00c (diff)
downloadsdl_ios-94e8660b1ff662b8739df92c0bccef5050139c98.tar.gz
Background task destroyed correctly
The secondary transport background task is now only destroyed after cleanup finishes
-rw-r--r--SmartDeviceLink/SDLBackgroundTaskManager.h13
-rw-r--r--SmartDeviceLink/SDLBackgroundTaskManager.m16
-rw-r--r--SmartDeviceLink/SDLSecondaryTransportManager.m2
-rw-r--r--SmartDeviceLink/SDLStreamingAudioLifecycleManager.m14
-rw-r--r--SmartDeviceLink/SDLStreamingVideoLifecycleManager.m14
5 files changed, 26 insertions, 33 deletions
diff --git a/SmartDeviceLink/SDLBackgroundTaskManager.h b/SmartDeviceLink/SDLBackgroundTaskManager.h
index edf02f991..7ed45f08d 100644
--- a/SmartDeviceLink/SDLBackgroundTaskManager.h
+++ b/SmartDeviceLink/SDLBackgroundTaskManager.h
@@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface SDLBackgroundTaskManager : NSObject
-/// Handler called when the background task has ended.
+/// Handler called when the background task is about to expire. Use this handler to perform some cleanup before the background task is destroyed. When you have finished cleanup, you must call the `endBackgroundTask` function so the background task can be destroyed. If you do not call `endBackgroundTask`, the system may kill the app.
@property (copy, nonatomic, nullable) void (^taskEndedHandler)(void);
- (instancetype)init NS_UNAVAILABLE;
@@ -29,17 +29,10 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (instancetype)initWithBackgroundTaskName:(NSString *)backgroundTaskName;
-/**
- * Starts a background task that allows the app to establish a session while app is backgrounded. If the app is not currently backgrounded, the background task will remain dormant until the app moves to the background.
- */
+/// Starts a background task. If the app is not currently backgrounded, the background task will remain dormant until the app moves to the background.
- (void)startBackgroundTask;
-/**
- * Cleans up a background task when it is stopped. This should be called when:
- *
- * 1. The app has established a session.
- * 2. The system has called the `expirationHandler` for the background task. The system may kill the app if the background task is not ended when `expirationHandler` is called.
- */
+/// Destroys the background task.
- (void)endBackgroundTask;
@end
diff --git a/SmartDeviceLink/SDLBackgroundTaskManager.m b/SmartDeviceLink/SDLBackgroundTaskManager.m
index 3cf10318e..4848073b4 100644
--- a/SmartDeviceLink/SDLBackgroundTaskManager.m
+++ b/SmartDeviceLink/SDLBackgroundTaskManager.m
@@ -41,26 +41,34 @@ NS_ASSUME_NONNULL_BEGIN
__weak typeof(self) weakSelf = self;
self.currentBackgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithName:self.backgroundTaskName expirationHandler:^{
+ // We have ~1 second to do cleanup before ending the background task. If we take too long, the system will kill the app.
__strong typeof(weakSelf) strongSelf = weakSelf;
SDLLogD(@"The background task %@ expired", strongSelf.backgroundTaskName);
- [strongSelf endBackgroundTask];
+ if (strongSelf.taskEndedHandler != nil) {
+ SDLLogD(@"Waiting for cleanup to finish before ending the background task");
+ strongSelf.taskEndedHandler();
+ } else {
+ [strongSelf endBackgroundTask];
+ }
}];
SDLLogD(@"The %@ background task started with id: %lu", self.backgroundTaskName, (unsigned long)self.currentBackgroundTaskId);
}
- (void)endBackgroundTask {
+ SDLLogV(@"Attempting to end background task %@", self.backgroundTaskName);
+
if (self.taskEndedHandler != nil) {
- self.taskEndedHandler();
+ SDLLogD(@"Background task %@ cleanup finished", self.backgroundTaskName);
self.taskEndedHandler = nil;
}
if (self.currentBackgroundTaskId == UIBackgroundTaskInvalid) {
- SDLLogV(@"Background task already ended. Returning...");
+ SDLLogV(@"Background task %@ with id %lu already ended. Returning...", self.backgroundTaskName, (unsigned long)self.currentBackgroundTaskId);
return;
}
- SDLLogD(@"Ending background task with id: %lu", (unsigned long)self.currentBackgroundTaskId);
+ SDLLogD(@"Ending background task %@ with id: %lu", self.backgroundTaskName, (unsigned long)self.currentBackgroundTaskId);
[[UIApplication sharedApplication] endBackgroundTask:self.currentBackgroundTaskId];
self.currentBackgroundTaskId = UIBackgroundTaskInvalid;
}
diff --git a/SmartDeviceLink/SDLSecondaryTransportManager.m b/SmartDeviceLink/SDLSecondaryTransportManager.m
index 7104c1754..9f996522d 100644
--- a/SmartDeviceLink/SDLSecondaryTransportManager.m
+++ b/SmartDeviceLink/SDLSecondaryTransportManager.m
@@ -703,7 +703,7 @@ struct TransportProtocolUpdated {
[strongSelf.backgroundTaskManager endBackgroundTask];
[strongSelf.stateMachine transitionToState:SDLSecondaryTransportStateConnecting];
} else {
- SDLLogD(@"TCP transport not ready to start, our current state is: %@, strongSelf.stateMachine.currentState");
+ SDLLogD(@"TCP transport not ready to start, our current state is: %@", strongSelf.stateMachine.currentState);
}
}
});
diff --git a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m
index 36e0f3920..50fb56dac 100644
--- a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m
+++ b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m
@@ -155,6 +155,11 @@ NS_ASSUME_NONNULL_BEGIN
_audioEncrypted = NO;
[[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil];
+
+ if (self.audioServiceEndedCompletionHandler != nil) {
+ self.audioServiceEndedCompletionHandler();
+ self.audioServiceEndedCompletionHandler = nil;
+ }
}
- (void)didEnterStateAudioStreamStarting {
@@ -210,12 +215,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)handleProtocolEndServiceACKMessage:(SDLProtocolMessage *)endServiceACK {
if (endServiceACK.header.serviceType != SDLServiceTypeAudio) { return; }
-
SDLLogD(@"Request to end audio service ACKed");
- if (self.audioServiceEndedCompletionHandler != nil) {
- self.audioServiceEndedCompletionHandler();
- self.audioServiceEndedCompletionHandler = nil;
- }
[self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateStopped];
}
@@ -225,10 +225,6 @@ NS_ASSUME_NONNULL_BEGIN
SDLControlFramePayloadNak *nakPayload = [[SDLControlFramePayloadNak alloc] initWithData:endServiceNAK.payload];
SDLLogE(@"Request to end audio service NAKed with playlod: %@", nakPayload);
- if (self.audioServiceEndedCompletionHandler != nil) {
- self.audioServiceEndedCompletionHandler();
- self.audioServiceEndedCompletionHandler = nil;
- }
/// Core will NAK the audio end service control frame if audio is not streaming or if video is streaming but the HMI does not recognize that audio is streaming.
[self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateStopped];
diff --git a/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m
index bdfa9968a..be9135cb8 100644
--- a/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m
+++ b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m
@@ -364,6 +364,11 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
[self sdl_disposeDisplayLink];
[[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStopNotification object:nil];
+
+ if (self.videoServiceEndedCompletionHandler != nil) {
+ self.videoServiceEndedCompletionHandler();
+ self.videoServiceEndedCompletionHandler = nil;
+ }
}
- (void)didEnterStateVideoStreamStarting {
@@ -560,12 +565,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
- (void)handleProtocolEndServiceACKMessage:(SDLProtocolMessage *)endServiceACK {
if (endServiceACK.header.serviceType != SDLServiceTypeVideo) { return; }
-
SDLLogD(@"Request to end video service ACKed");
- if (self.videoServiceEndedCompletionHandler != nil) {
- self.videoServiceEndedCompletionHandler();
- self.videoServiceEndedCompletionHandler = nil;
- }
[self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped];
}
@@ -575,10 +575,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
SDLControlFramePayloadNak *nakPayload = [[SDLControlFramePayloadNak alloc] initWithData:endServiceNAK.payload];
SDLLogE(@"Request to end video service NAKed with payload: %@", nakPayload);
- if (self.videoServiceEndedCompletionHandler != nil) {
- self.videoServiceEndedCompletionHandler();
- self.videoServiceEndedCompletionHandler = nil;
- }
/// Core will NAK the video end service control frame if video is not streaming or if video is streaming but the HMI does not recognize that video is streaming.
[self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped];