Skip to content

Commit

Permalink
Merge pull request #199 from shankari/native_upgrade_2021
Browse files Browse the repository at this point in the history
Fix start state issue by ensuring that we restart the FSM if in start…
  • Loading branch information
shankari authored Jul 10, 2022
2 parents a2b3e26 + abfd2af commit 0756d2d
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 54 deletions.
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
id="cordova-plugin-em-datacollection"
version="1.7.2">
version="1.7.3">

<name>DataCollection</name>
<description>Background data collection FTW! This is the part that I really
Expand Down
2 changes: 2 additions & 0 deletions src/ios/BEMDataCollection.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#import "StatsEvent.h"
#import "BEMBuiltinUserCache.h"
#import "SensorControlForegroundDelegate.h"
#import "SensorControlBackgroundChecker.h"
#import <CoreLocation/CoreLocation.h>

@implementation BEMDataCollection
Expand Down Expand Up @@ -46,6 +47,7 @@ - (id)settingForKey:(NSString*)key

- (void)initWithConsent {
self.tripDiaryStateMachine = [TripDiaryStateMachine instance];
[SensorControlBackgroundChecker checkAppState];
NSDictionary* emptyOptions = @{};
[AppDelegate didFinishLaunchingWithOptions:emptyOptions];
}
Expand Down
1 change: 1 addition & 0 deletions src/ios/ConfigManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

+ (LocationTrackingConfig*) instance;
+ (void) updateConfig:(LocationTrackingConfig*) newConfig;
+ (ConsentConfig*) getPriorConsent;
+ (BOOL) isConsented:(NSString*)reqConsent;
+ (void) setConsented:(ConsentConfig*) newConfig;
@end
6 changes: 6 additions & 0 deletions src/ios/ConfigManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ + (void) updateConfig:(LocationTrackingConfig*) newConfig {
_instance = newConfig;
}

+ (ConsentConfig*) getPriorConsent {
ConsentConfig* currConfig = (ConsentConfig*)[[BuiltinUserCache database] getDocument:CONSENT_CONFIG_KEY wrapperClass:[ConsentConfig class]];
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"in getPriorConsent, currConfig = %@", currConfig]];
return currConfig;
}

+ (BOOL) isConsented:(NSString*)reqConsent {
@try {
ConsentConfig* currConfig = (ConsentConfig*)[[BuiltinUserCache database] getDocument:CONSENT_CONFIG_KEY wrapperClass:[ConsentConfig class]];
Expand Down
40 changes: 7 additions & 33 deletions src/ios/Location/TripDiaryStateMachine.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ - (id) init {
_geofenceLocator = [GeofenceActions new];

// The operations in the one time init tracking are idempotent, so let's start them anyway
[TripDiaryActions oneTimeInitTracking:CFCTransitionInitialize withLocationMgr:self.locMgr];
if ([ConfigManager getPriorConsent] != NULL) {
[TripDiaryActions oneTimeInitTracking:CFCTransitionInitialize withLocationMgr:self.locMgr];
}

[LocalNotificationManager addNotification:[NSString stringWithFormat:
@"initializing TripDiaryStateMachine with state = %@",
Expand All @@ -104,38 +106,10 @@ - (id) init {
// would be good to test, though.
}

// STATUS SCREEN: Figure out how to fix recursion when [TripDiaryStateMachine instance] is called
// [SensorControlBackgroundChecker checkAppState];
/* The only times we should get here are:
* - if we re-install a previously installed app, and so it is already authorized for background location collection BUT is in the start state, or
* - another option might be a re-launch of the app when the user has manually stopped tracking.
* It would be bad to automatically restart the tracking if the user has manully stopped tracking.
* One way to deal with this would be to have separate states for "start" and for "tracking suspended".
* Another way would be to just remove this transition from here...
* TODO: Figure out how to deal with it.
*/
// STATUS SCREEN: Figure out how to fix recursion when [TripDiaryStateMachine instance] is called
// [SensorControlBackgroundChecker restartFSMIfStartState];
/*
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways) {
[TripDiarySettingsCheck promptForPermission:self.locMgr];
} else {
NSLog(@"Current location authorization = %d, always = %d",
[CLLocationManager authorizationStatus], kCLAuthorizationStatusAuthorizedAlways);
The only times we should get here are:
* - if we re-install a previously installed app, and so it is already authorized for background location collection BUT is in the start state, or
* - another option might be a re-launch of the app when the user has manually stopped tracking.
* It would be bad to automatically restart the tracking if the user has manully stopped tracking.
* One way to deal with this would be to have separate states for "start" and for "tracking suspended".
* Another way would be to just remove this transition from here...
* TODO: Figure out how to deal with it.
if (self.currState == kStartState) {
[[NSNotificationCenter defaultCenter] postNotificationName:CFCTransitionNotificationName
object:CFCTransitionInitialize];
}
}
*/
// Replaced by a call to [SensorControlBackgroundChecker checkAppState]
// just after the initialization is complete in the background
// currently only in `BEMDataCollection initWithConsent`
// https://github.com/e-mission/e-mission-docs/issues/735#issuecomment-1179774103

if (![ConfigManager instance].is_duty_cycling && self.currState != kTrackingStoppedState) {
/* If we are not using geofencing, and the tracking is not manually turned off, then we don't need to listen
Expand Down
37 changes: 18 additions & 19 deletions src/ios/Verification/SensorControlBackgroundChecker.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#import "LocalNotificationManager.h"
#import "BEMAppDelegate.h"
#import "BEMActivitySync.h"
#import "ConfigManager.h"

#import <CoreMotion/CoreMotion.h>
#define OPEN_APP_STATUS_PAGE_ID @362253744
Expand Down Expand Up @@ -60,26 +61,24 @@ +(void)checkAppState
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"All settings valid, nothing to prompt"]];
[self restartFSMIfStartState];
}
else if (locChecksPass) {
/*
Log.i(ctxt, TAG, "all checks = "+allOtherChecksPass+" but location permission status "+allOtherChecks[0]+" should be true "+
" so one of the non-location checks must be false: loc permission, motion permission, notification, unused apps" + Arrays.toString(allOtherChecks));
Log.i(ctxt, TAG, "a non-local check failed, generating only user visible notification");
*/
[self generateOpenAppSettingsNotification];
}
else {
/*
Log.i(ctxt, TAG, "location settings are valid, but location permission is not, generating tracking error and visible notification");
Log.i(ctxt, TAG, "curr status check results = " +
" loc permission, motion permission, notification, unused apps "+ Arrays.toString(allOtherChecks));
*/
// Should replace with TRACKING_ERROR but looks like we
// don't have any
[[NSNotificationCenter defaultCenter]
postNotificationName:CFCTransitionNotificationName
object:CFCTransitionGeofenceCreationError];
[self generateOpenAppSettingsNotification];
if ([ConfigManager getPriorConsent] == NULL) {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"User has not yet consented, ignoring failed checks"]];
} else {
if (locChecksPass) {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"allChecksPass = %@, but location permimssions pass, so one of the non-location checks must be false: [loc settings, loc permissions, motion settings, motion permissions, notification] = %@", @(allChecksPass), allChecks]];
[self generateOpenAppSettingsNotification];
}
else {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"allChecksPass = %@, but location checks fail, generating error and notification, allChecks: [loc settings, loc permissions, motion settings, motion permissions, notification] = %@", @(allChecksPass), allChecks]];
// Should replace with TRACKING_ERROR but looks like we
// don't have any
[[NSNotificationCenter defaultCenter]
postNotificationName:CFCTransitionNotificationName
object:CFCTransitionGeofenceCreationError];
[self generateOpenAppSettingsNotification];
}
}
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/ios/Verification/SensorControlForegroundDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,18 @@ -(void) checkAndPromptLocationPermissions

- (void) didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"In delegate didChangeAuthorizationStatus, newStatus = %d", status]];
[[TripDiaryStateMachine instance].locMgr stopUpdatingLocation];
NSString* callbackId = [command callbackId];
@try {
if (status == kCLAuthorizationStatusAuthorizedAlways) {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"status == always, restarting FSM if start state"]];
[SensorControlBackgroundChecker restartFSMIfStartState];
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK];
[commandDelegate sendPluginResult:result callbackId:callbackId];
} else {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"status %d != always %d, returning error", status, kCLAuthorizationStatusAuthorizedAlways]];
NSString* msg = NSLocalizedStringFromTable(@"location_permission_off_app_open", @"DCLocalizable", nil);
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_ERROR
Expand Down Expand Up @@ -340,13 +344,16 @@ - (void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"In checker's didChangeAuthorizationStatus, new authorization status = %d, always = %d", status, kCLAuthorizationStatusAuthorizedAlways]];

[LocalNotificationManager addNotification:[NSString stringWithFormat:@"Calling TripDiarySettingsCheck from didChangeAuthorizationStatus to verify location service status and permission"]];
if (foregroundDelegateList.count > 0) {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"%lu foreground delegates found, calling didChangeAuthorizationStatus to return the new value %d", (unsigned long)foregroundDelegateList.count, status]];

for (id currDelegate in foregroundDelegateList) {
[currDelegate didChangeAuthorizationStatus:(CLAuthorizationStatus)status];
}
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"Notified all foreground delegates, removing all of them"]];
[foregroundDelegateList removeAllObjects];
} else {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"No foreground delegate found, calling SensorControlBackgroundChecker from didChangeAuthorizationStatus to verify location service status and permission"]];
[SensorControlBackgroundChecker checkAppState];
}
}
Expand Down

0 comments on commit 0756d2d

Please sign in to comment.