Skip to content

Commit

Permalink
Merge pull request #1317 from smartdevicelink/bugfix/issue_1316_backg…
Browse files Browse the repository at this point in the history
…round_task_session_creation_fails

Fixed session creation failing due to no background task
  • Loading branch information
joeljfischer committed Jun 26, 2019
2 parents cb4f94e + b8098be commit b6a19fc
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 94 deletions.
8 changes: 8 additions & 0 deletions SmartDeviceLink-iOS.xcodeproj/project.pbxproj
Expand Up @@ -1238,6 +1238,8 @@
756C62772289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.m in Sources */ = {isa = PBXBuildFile; fileRef = 756C62752289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.m */; };
880245A420F79C3400ED195B /* SDLFileManagerConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 880245A220F79C3400ED195B /* SDLFileManagerConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
880245A520F79C3400ED195B /* SDLFileManagerConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 880245A320F79C3400ED195B /* SDLFileManagerConfiguration.m */; };
8803DCEF22C2B84B00FBB7CE /* SDLBackgroundTaskManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 8803DCED22C2B84B00FBB7CE /* SDLBackgroundTaskManager.h */; };
8803DCF022C2B84B00FBB7CE /* SDLBackgroundTaskManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8803DCEE22C2B84B00FBB7CE /* SDLBackgroundTaskManager.m */; };
880D267A220DDD1000B3F496 /* SDLWeatherServiceDataSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 880D2679220DDD1000B3F496 /* SDLWeatherServiceDataSpec.m */; };
880D267D220DE5DF00B3F496 /* SDLWeatherServiceManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 880D267B220DE5DF00B3F496 /* SDLWeatherServiceManifest.h */; settings = {ATTRIBUTES = (Public, ); }; };
880D267E220DE5DF00B3F496 /* SDLWeatherServiceManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 880D267C220DE5DF00B3F496 /* SDLWeatherServiceManifest.m */; };
Expand Down Expand Up @@ -2892,6 +2894,8 @@
756C62752289F11F008B57A2 /* SDLDynamicMenuUpdateRunScore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLDynamicMenuUpdateRunScore.m; sourceTree = "<group>"; };
880245A220F79C3400ED195B /* SDLFileManagerConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLFileManagerConfiguration.h; sourceTree = "<group>"; };
880245A320F79C3400ED195B /* SDLFileManagerConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLFileManagerConfiguration.m; sourceTree = "<group>"; };
8803DCED22C2B84B00FBB7CE /* SDLBackgroundTaskManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLBackgroundTaskManager.h; sourceTree = "<group>"; };
8803DCEE22C2B84B00FBB7CE /* SDLBackgroundTaskManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLBackgroundTaskManager.m; sourceTree = "<group>"; };
880D2679220DDD1000B3F496 /* SDLWeatherServiceDataSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLWeatherServiceDataSpec.m; sourceTree = "<group>"; };
880D267B220DE5DF00B3F496 /* SDLWeatherServiceManifest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLWeatherServiceManifest.h; sourceTree = "<group>"; };
880D267C220DE5DF00B3F496 /* SDLWeatherServiceManifest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLWeatherServiceManifest.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4791,6 +4795,8 @@
5D5934F61A85189500687FB9 /* Utilities */ = {
isa = PBXGroup;
children = (
8803DCED22C2B84B00FBB7CE /* SDLBackgroundTaskManager.h */,
8803DCEE22C2B84B00FBB7CE /* SDLBackgroundTaskManager.m */,
97E26DEA1E807AD70074A3C7 /* SDLMutableDataQueue.h */,
97E26DEB1E807AD70074A3C7 /* SDLMutableDataQueue.m */,
E9C32B831AB20B2900F283AF /* @categories */,
Expand Down Expand Up @@ -6426,6 +6432,7 @@
5D61FC511A84238C00846EE7 /* SDLButtonCapabilities.h in Headers */,
5D61FDE91A84238C00846EE7 /* SDLUnsubscribeButtonResponse.h in Headers */,
5D61FCD51A84238C00846EE7 /* SDLImageType.h in Headers */,
8803DCEF22C2B84B00FBB7CE /* SDLBackgroundTaskManager.h in Headers */,
5D61FC2F1A84238C00846EE7 /* SDLAddCommandResponse.h in Headers */,
5D0C2A0020D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h in Headers */,
5D61FD631A84238C00846EE7 /* SDLResetGlobalProperties.h in Headers */,
Expand Down Expand Up @@ -7204,6 +7211,7 @@
5D61FC5E1A84238C00846EE7 /* SDLChangeRegistrationResponse.m in Sources */,
5D8204231BCEA89A00D0A41B /* SDLFileManager.m in Sources */,
1EB59CC0202DA26000343A61 /* SDLSeatControlData.m in Sources */,
8803DCF022C2B84B00FBB7CE /* SDLBackgroundTaskManager.m in Sources */,
5D61FC7D1A84238C00846EE7 /* SDLDeleteInteractionChoiceSetResponse.m in Sources */,
DAC572661D10C5640004288B /* CGPoint_Util.m in Sources */,
5D00AC681F140F0A004000D9 /* SDLSystemCapabilityType.m in Sources */,
Expand Down
44 changes: 44 additions & 0 deletions SmartDeviceLink/SDLBackgroundTaskManager.h
@@ -0,0 +1,44 @@
//
// SDLBackgroundTaskManager.h
// SmartDeviceLink
//
// Created by Nicole on 6/25/19.
// Copyright © 2019 smartdevicelink. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

/**
* Class for managing a background task.
*/
@interface SDLBackgroundTaskManager : NSObject

- (instancetype)init NS_UNAVAILABLE;

/**
* Convenience init for starting a background task with a specific name.
*
* @param backgroundTaskName The name for the background task
* @return A SDLBackgroundTaskManager object
*/
- (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.
*/
- (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.
*/
- (void)endBackgroundTask;

@end

NS_ASSUME_NONNULL_END
68 changes: 68 additions & 0 deletions SmartDeviceLink/SDLBackgroundTaskManager.m
@@ -0,0 +1,68 @@
//
// SDLBackgroundTaskManager.m
// SmartDeviceLink
//
// Created by Nicole on 6/25/19.
// Copyright © 2019 smartdevicelink. All rights reserved.
//

#import "SDLBackgroundTaskManager.h"

#import "SDLLogMacros.h"


NS_ASSUME_NONNULL_BEGIN

@interface SDLBackgroundTaskManager ()
@property (copy, nonatomic) NSString *backgroundTaskName;
@property (assign, nonatomic) UIBackgroundTaskIdentifier currentBackgroundTaskId;

@end

@implementation SDLBackgroundTaskManager

- (instancetype)initWithBackgroundTaskName:(NSString *)backgroundTaskName {
SDLLogV(@"SDLBackgroundTaskManager init with name %@", backgroundTaskName);
self = [super init];
if (!self) {
return nil;
}

_backgroundTaskName = backgroundTaskName;

return self;
}

- (void)startBackgroundTask {
if (self.currentBackgroundTaskId != UIBackgroundTaskInvalid) {
SDLLogV(@"The %@ background task is already running.", self.backgroundTaskName);
return;
}

__weak typeof(self) weakself = self;
self.currentBackgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithName:self.backgroundTaskName expirationHandler:^{
SDLLogD(@"The %@ background task expired", self.backgroundTaskName);
[weakself endBackgroundTask];
}];

SDLLogD(@"The %@ background task started with id: %lu", self.backgroundTaskName, (unsigned long)self.currentBackgroundTaskId);
}

- (void)endBackgroundTask {
if (self.currentBackgroundTaskId == UIBackgroundTaskInvalid) {
SDLLogV(@"Background task already ended. Returning...");
return;
}

SDLLogD(@"Ending background task with id: %lu", (unsigned long)self.currentBackgroundTaskId);
[[UIApplication sharedApplication] endBackgroundTask:self.currentBackgroundTaskId];
self.currentBackgroundTaskId = UIBackgroundTaskInvalid;
}

- (void)dealloc {
[self endBackgroundTask];
}

@end

NS_ASSUME_NONNULL_END
87 changes: 2 additions & 85 deletions SmartDeviceLink/SDLIAPTransport.m
Expand Up @@ -15,12 +15,10 @@
#import "SDLIAPDataSession.h"
#import "SDLIAPDataSessionDelegate.h"
#import "SDLLogMacros.h"
#import "SDLTimer.h"
#import <CommonCrypto/CommonDigest.h>

NS_ASSUME_NONNULL_BEGIN

NSString *const BackgroundTaskName = @"com.sdl.transport.iap.backgroundTask";
int const CreateSessionRetries = 3;

@interface SDLIAPTransport () <SDLIAPControlSessionDelegate, SDLIAPDataSessionDelegate>
Expand All @@ -30,7 +28,6 @@ @interface SDLIAPTransport () <SDLIAPControlSessionDelegate, SDLIAPDataSessionDe
@property (assign, nonatomic) int retryCounter;
@property (assign, nonatomic) BOOL sessionSetupInProgress;
@property (assign, nonatomic) BOOL transportDestroyed;
@property (nonatomic, assign) UIBackgroundTaskIdentifier backgroundTaskId;
@property (assign, nonatomic) BOOL accessoryConnectDuringActiveSession;

@end
Expand Down Expand Up @@ -60,39 +57,6 @@ - (instancetype)init {
return self;
}

#pragma mark - Background Task

/**
* Starts a background task that allows the app to search for accessories and while the app is in the background.
*/
- (void)sdl_backgroundTaskStart {
if (self.backgroundTaskId != UIBackgroundTaskInvalid) {
SDLLogV(@"A background task is already running. No need to start a background task.");
return;
}

self.backgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithName:BackgroundTaskName expirationHandler:^{
SDLLogD(@"Background task expired");
[self sdl_backgroundTaskEnd];
}];

SDLLogD(@"Started a background task with id: %lu", (unsigned long)self.backgroundTaskId);
}

/**
* Cleans up a background task when it is stopped.
*/
- (void)sdl_backgroundTaskEnd {
if (self.backgroundTaskId == UIBackgroundTaskInvalid) {
SDLLogV(@"No background task running. No need to stop the background task. Returning...");
return;
}

SDLLogD(@"Ending background task with id: %lu", (unsigned long)self.backgroundTaskId);
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskId];
self.backgroundTaskId = UIBackgroundTaskInvalid;
}

#pragma mark - Notifications

/**
Expand All @@ -108,14 +72,6 @@ - (void)sdl_startEventListening {
selector:@selector(sdl_accessoryDisconnected:)
name:EAAccessoryDidDisconnectNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sdl_applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sdl_applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];
}

Expand All @@ -125,7 +81,6 @@ - (void)sdl_startEventListening {
- (void)sdl_stopEventListening {
SDLLogV(@"SDLIAPTransport stopped listening for events");
[[EAAccessoryManager sharedAccessoryManager] unregisterForLocalNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark EAAccessory Notifications
Expand All @@ -145,11 +100,6 @@ - (void)sdl_accessoryConnected:(NSNotification *)notification {

double retryDelay = self.sdl_retryDelay;
SDLLogD(@"Accessory Connected (%@), Opening in %0.03fs", notification.userInfo[EAAccessoryKey], retryDelay);

if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) {
SDLLogD(@"Accessory connected while app is in background. Starting background task.");
[self sdl_backgroundTaskStart];
}

self.retryCounter = 0;
[self performSelector:@selector(sdl_connect:) withObject:nil afterDelay:retryDelay];
Expand Down Expand Up @@ -182,7 +132,7 @@ - (BOOL)sdl_isDataSessionActive:(nullable SDLIAPDataSession *)dataSession newAcc
*/
- (void)sdl_accessoryDisconnected:(NSNotification *)notification {
EAAccessory *accessory = [notification.userInfo objectForKey:EAAccessoryKey];
SDLLogD(@"Accessory with serial number %@ and connectionID %lu disconnecting.", accessory.serialNumber, (unsigned long)accessory.connectionID);
SDLLogD(@"Accessory with serial number: %@, and connectionID: %lu disconnecting.", accessory.serialNumber, (unsigned long)accessory.connectionID);

if (self.accessoryConnectDuringActiveSession == YES) {
SDLLogD(@"Switching transports from Bluetooth to USB. Will reconnect over Bluetooth after disconnecting the USB session.");
Expand Down Expand Up @@ -227,31 +177,6 @@ - (void)sdl_destroyTransport {
[self.delegate onTransportDisconnected];
}

#pragma mark App Lifecycle Notifications

/**
* Handles a notification sent by the system when the app enters the foreground.
*
* If the app is still searching for an accessory, a background task will be started so the app can still search for and/or connect with an accessory while it is in the background.
*
* @param notification Notification
*/
- (void)sdl_applicationWillEnterForeground:(NSNotification *)notification {
SDLLogV(@"App foregrounded, attempting connection");
[self sdl_backgroundTaskEnd];
[self connect];
}

/**
* Handles a notification sent by the system when the app enters the background.
*
* @param notification Notification
*/
- (void)sdl_applicationDidEnterBackground:(NSNotification *)notification {
SDLLogV(@"App backgrounded, starting background task");
[self sdl_backgroundTaskStart];
}

#pragma mark - Stream Lifecycle

#pragma mark SDLTransportTypeProtocol
Expand All @@ -273,12 +198,6 @@ - (void)sendData:(NSData *)data {
* Attempts to connect to an accessory.
*/
- (void)connect {
UIApplicationState state = [UIApplication sharedApplication].applicationState;
if (state != UIApplicationStateActive) {
SDLLogV(@"App inactive on connect, starting background task");
[self sdl_backgroundTaskStart];
}

[self sdl_connect:nil];
}

Expand Down Expand Up @@ -329,7 +248,7 @@ - (void)sdl_connect:(nullable EAAccessory *)accessory {
* @param accessory The accessory to try to establish a session with, or nil to scan all connected accessories.
*/
- (void)sdl_establishSessionWithAccessory:(nullable EAAccessory *)accessory {
SDLLogD(@"Attempting to connect accessory: %@", accessory.name);
SDLLogD(@"Attempting to connect accessory named: %@, with connectionID: %lu", accessory.name, (unsigned long)accessory.connectionID);
if (self.retryCounter < CreateSessionRetries) {
self.retryCounter++;

Expand Down Expand Up @@ -399,7 +318,6 @@ - (void)controlSession:(nonnull SDLIAPControlSession *)controlSession didReceive
*/
- (void)dataSessionDidReceiveData:(nonnull NSData *)data {
[self.delegate onDataReceived:data];
[self sdl_backgroundTaskStart];
}

/**
Expand Down Expand Up @@ -598,7 +516,6 @@ - (BOOL)createSessionWithAccessory:(EAAccessory *)accessory protocolString:(NSSt
- (void)dealloc {
SDLLogV(@"SDLIAPTransport dealloc");
[self disconnect];
[self sdl_backgroundTaskEnd];
self.controlSession = nil;
self.dataSession = nil;
self.delegate = nil;
Expand Down

0 comments on commit b6a19fc

Please sign in to comment.