public static void Enqueue( Context context, JobSetting jobSetting ) { JobInfo.Builder jobInfoBuilder = new JobInfo.Builder( JOB_ID, new ComponentName(context, Java.Lang.Class.FromType(typeof(ExposureNotDetectedJob)))) .SetOverrideDeadline(0); if (jobSetting != null) { jobSetting.Apply(jobInfoBuilder); } JobInfo jobInfo = jobInfoBuilder.Build(); JobScheduler jobScheduler = (JobScheduler)context.GetSystemService(JobSchedulerService); int result = jobScheduler.Schedule(jobInfo); if (result == JobScheduler.ResultSuccess) { Logger.D("ExposureNotDetectedJob scheduled"); } else if (result == JobScheduler.ResultFailure) { Logger.D("ExposureNotDetectedJob schedule failed"); } }
private async Task <IList <TemporaryExposureKey> > GetReleasedTemporaryExposureKeys( ExposureNotificationClient enClient, Context appContext ) { TaskCompletionSource <Intent> taskCompletionSource = new TaskCompletionSource <Intent>(TaskCreationOptions.RunContinuationsAsynchronously); BroadcastReceiver receiver = new PreAuthorizeReleasePhoneUnlockedBroadcastReceiver(taskCompletionSource); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(API_TIMEOUT_MILLIS); using (cancellationTokenSource.Token.Register(() => { Logger.D("cancellationTokenSource canceled."); taskCompletionSource.TrySetCanceled(); appContext.UnregisterReceiver(receiver); })) { appContext.RegisterReceiver( receiver, INTENT_FILTER_PRE_AUTHORIZE_RELEASE_PHONE_UNLOCKED ); await enClient.RequestPreAuthorizedTemporaryExposureKeyReleaseAsync(); Intent intent = await taskCompletionSource.Task; IList <TemporaryExposureKey> temporaryExposureKeys = intent.GetParcelableArrayListExtra(EXTRA_TEMPORARY_EXPOSURE_KEY_LIST) .Cast <AndroidTemporaryExposureKey>() .Select(tek => (TemporaryExposureKey) new PlatformTemporaryExposureKey(tek)) .ToList(); return(temporaryExposureKeys); } }
public override bool OnStartJob(JobParameters @params) { IExposureNotificationHandler?handler = null; ExposureNotificationClient? enClient = null; if (ApplicationContext is IExposureNotificationHandler exposureNotificationHandler) { handler = exposureNotificationHandler; enClient = (ExposureNotificationClient)exposureNotificationHandler.GetEnClient(); } if (enClient is null) { Logger.E("ExposureDetectedV2Job: enClient is null."); return(false); } if (handler is null) { Logger.E("ExposureDetectedV2Job: handler is null."); return(false); } _ = Task.Run(async() => { try { ExposureConfiguration exposureConfiguration = await handler.GetExposureConfigurationAsync(); if (exposureConfiguration is null) { throw new IllegalStateException("ExposureConfiguration is null."); } await handler.PreExposureDetectedAsync(exposureConfiguration); var(dailySummaries, exposureWindows) = await GetExposureV2Async(enClient, exposureConfiguration); await handler.ExposureDetectedAsync(dailySummaries, exposureWindows, exposureConfiguration); } catch (ApiException exception) { if (exception.IsENException()) { var enException = exception.ToENException(); await handler.ExceptionOccurredAsync(enException); throw enException; } else { await handler.ExceptionOccurredAsync(exception); throw; } } finally { JobFinished(@params, false); } }); return(true); }
public static void Enqueue( Context context, string token, JobSetting jobSetting ) { PersistableBundle bundle = new PersistableBundle(); bundle.PutString(EXTRA_TOKEN, token); JobInfo.Builder jobInfoBuilder = new JobInfo.Builder( JOB_ID, new ComponentName(context, Java.Lang.Class.FromType(typeof(ExposureDetectedV1Job)))) .SetExtras(bundle) .SetOverrideDeadline(0); if (jobSetting != null) { jobSetting.Apply(jobInfoBuilder); } JobInfo jobInfo = jobInfoBuilder.Build(); JobScheduler jobScheduler = (JobScheduler)context.GetSystemService(JobSchedulerService); int result = jobScheduler.Schedule(jobInfo); if (result == JobScheduler.ResultSuccess) { Logger.D("ExposureDetectedV1Job scheduled"); } else if (result == JobScheduler.ResultFailure) { Logger.D("ExposureDetectedV1Job schedule failed"); } }
private IExposureNotificationClient GetEnClient() { if (EnClient is null) { Logger.E("Init method must be called first."); throw new UnInitializedException("Init method must be called first."); } return(EnClient); }
public override async Task RequestPreAuthorizedTemporaryExposureKeyReleaseAsync() { Logger.D("RequestPreAuthorizedTemporaryExposureKeyReleaseAsync"); IExposureNotificationHandler?handler = null; ExposureNotificationClient? enClient = null; if (_appContext is null) { throw new IllegalStateException("IExposureNotificationHandler is not set."); } if (_appContext is IExposureNotificationHandler exposureNotificationHandler) { handler = exposureNotificationHandler; enClient = (ExposureNotificationClient)exposureNotificationHandler.GetEnClient(); } if (handler is null) { Logger.E("TemporaryExposureKeyReleasedJob: handler is null."); return; } if (enClient is null) { Logger.E("TemporaryExposureKeyReleasedJob: enClient is null."); return; } try { IList <TemporaryExposureKey> temporaryExposureKeys = await GetReleasedTemporaryExposureKeys(enClient, _appContext); await handler.TemporaryExposureKeyReleasedAsync(temporaryExposureKeys); } catch (JavaTimeoutException exception) { // Wrap exception throw new TimeoutException(exception.Message); } catch (ApiException exception) { if (exception.IsENException()) { throw exception.ToENException(); } throw; } finally { } }
private static ENManager CreateEnManager() => new ENManager() { DiagnosisKeysAvailableHandler = new ENDiagnosisKeysAvailableHandler(async teks => { if (Handler is null) { Logger.E("ENDiagnosisKeysAvailableHandler is called but ENDiagnosisKeysAvailableHandler is not set."); return; } IList <TemporaryExposureKey> temporaryExposureKeys = teks.Select(tek => (TemporaryExposureKey) new PlatformTemporaryExposureKey(tek)).ToList(); await Handler.TemporaryExposureKeyReleasedAsync(temporaryExposureKeys); }) };
private async Task <(ExposureSummary, IList <ExposureInformation> exposureInformations)> GetExposureV1Async( ExposureNotificationClient enClient, string token ) { Logger.D($"GetExposureV1Async"); AndroidExposureSummary exposureSummary = await enClient.EnClient.GetExposureSummaryAsync(token); IList <AndroidExposureInformation> eis = await enClient.EnClient.GetExposureInformationAsync(token); IList <ExposureInformation> exposureInformations = eis.Select(ei => (ExposureInformation) new PlatformExposureInformation(ei)).ToList(); return(new PlatformExposureSummary(exposureSummary), exposureInformations); }
private async Task <(List <DailySummary> dailySummaries, List <ExposureWindow> exposureWindows)> GetExposureV2Async( ExposureNotificationClient enClient, ExposureConfiguration exposureConfiguration ) { Logger.D($"GetExposureV2Async"); IList <AndroidDailySummary> dss = await enClient.EnClient.GetDailySummariesAsync( exposureConfiguration.GoogleDailySummariesConfig.ToAndroidDailySummariesConfig() ); List <DailySummary> dailySummaries = dss.Select(ds => (DailySummary) new PlatformDailySummary(ds)).ToList(); IList <AndroidExposureWindow> ews = await enClient.EnClient.GetExposureWindowsAsync(); List <ExposureWindow> exposureWindows = ews.Select(ew => (ExposureWindow) new PlatformExposureWindow(ew)).ToList(); return(dailySummaries, exposureWindows); }
public override bool OnStartJob(JobParameters @params) { IExposureNotificationHandler?handler = null; ExposureNotificationClient? enClient = null; if (ApplicationContext is IExposureNotificationHandler exposureNotificationHandler) { handler = exposureNotificationHandler; enClient = (ExposureNotificationClient)exposureNotificationHandler.GetEnClient(); } if (enClient is null) { Logger.E("ExposureDetectedV2Job: enClient is null."); return(false); } if (handler is null) { Logger.E("ExposureDetectedV2Job: handler is null."); return(false); } _ = Task.Run(async() => { try { ExposureConfiguration exposureConfiguration = await handler.GetExposureConfigurationAsync(); if (exposureConfiguration is null) { throw new IllegalStateException("ExposureConfiguration is null."); } await handler.ExposureNotDetectedAsync(exposureConfiguration); } finally { JobFinished(@params, false); } }); return(true); }
public override void OnReceive(Context context, Intent intent) { Logger.D($"ACTION_PRE_AUTHORIZE_RELEASE_PHONE_UNLOCKED"); context.UnregisterReceiver(this); _taskCompletionSource.SetResult(intent); }
public override async Task <ProvideDiagnosisKeysResult> ProvideDiagnosisKeysAsync( List <string> keyFiles, string token, CancellationTokenSource?cancellationTokenSource = null ) { var enClient = GetEnClient(); Logger.D($"DiagnosisKey {keyFiles.Count}"); if (keyFiles.Count == 0) { Logger.D($"No DiagnosisKey found."); return(ProvideDiagnosisKeysResult.NoDiagnosisKeyFound); } if (Handler is null) { throw new IllegalStateException("IExposureNotificationHandler is not set."); } ExposureConfiguration configuration = await Handler.GetExposureConfigurationAsync(); if (configuration is null) { throw new IllegalStateException("ExposureConfiguration is null."); } TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); // Check and add taskCompletionSource for prevent multiple starts. lock (ExposureStateBroadcastReceiveTaskCompletionSourceDict) { Logger.D($"ExposureStateBroadcastReceiveTaskCompletionSourceDict count {ExposureStateBroadcastReceiveTaskCompletionSourceDict.Count}"); if (ExposureStateBroadcastReceiveTaskCompletionSourceDict.ContainsKey(token)) { Logger.E($"Task ProvideDiagnosisKeysAsync(Legacy-V1 mode) token {token} is already started."); return(ProvideDiagnosisKeysResult.Completed); } ExposureStateBroadcastReceiveTaskCompletionSourceDict.Add(token, taskCompletionSource); } cancellationTokenSource ??= new CancellationTokenSource(API_PROVIDE_DIAGNOSIS_KEYS_TIMEOUT_MILLIS); var files = keyFiles.Select(f => new File(f)).ToList(); try { using (cancellationTokenSource.Token.Register(() => { Logger.D("ProvideDiagnosisKeysAsync cancellationTokenSource canceled."); taskCompletionSource?.TrySetException( new TimeoutException($"ExposureStateBroadcastReceiver was not called in {API_PROVIDE_DIAGNOSIS_KEYS_TIMEOUT_MILLIS} millis.") ); lock (ExposureStateBroadcastReceiveTaskCompletionSourceDict) { ExposureStateBroadcastReceiveTaskCompletionSourceDict.Remove(token); } })) { await enClient.ProvideDiagnosisKeysAsync(files, configuration.ToAndroidExposureConfiguration(), token); _ = await taskCompletionSource.Task; lock (ExposureStateBroadcastReceiveTaskCompletionSourceDict) { ExposureStateBroadcastReceiveTaskCompletionSourceDict.Remove(token); } } Logger.D("ExposureStateBroadcastReceiveTaskCompletionSource is completed."); return(ProvideDiagnosisKeysResult.Completed); } catch (JavaTimeoutException exception) { // Wrap exception throw new TimeoutException(exception.Message); } catch (ApiException exception) { if (exception.IsENException()) { throw exception.ToENException(); } throw; } }
public override async Task <ProvideDiagnosisKeysResult> ProvideDiagnosisKeysAsync( List <string> keyFiles, CancellationTokenSource?cancellationTokenSource = null ) { var enClient = GetEnClient(); Logger.D($"DiagnosisKey {keyFiles.Count}"); if (keyFiles.Count == 0) { Logger.D($"No DiagnosisKey found."); return(ProvideDiagnosisKeysResult.NoDiagnosisKeyFound); } if (Handler is null) { throw new IllegalStateException("IExposureNotificationHandler is not set."); } ExposureConfiguration configuration = await Handler.GetExposureConfigurationAsync(); if (configuration is null) { throw new IllegalStateException("ExposureConfiguration is null."); } string token = Guid.NewGuid().ToString(); TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); // Check and add taskCompletionSource for prevent multiple starts. lock (ExposureStateBroadcastReceiveTaskCompletionSourceDict) { Logger.D($"ExposureStateBroadcastReceiveTaskCompletionSourceDict count {ExposureStateBroadcastReceiveTaskCompletionSourceDict.Count}"); if (ExposureStateBroadcastReceiveTaskCompletionSourceDict.Count > 0) { Logger.E($"Task ProvideDiagnosisKeysAsync(ExposureWindow mode) is already started."); return(ProvideDiagnosisKeysResult.Completed); } ExposureStateBroadcastReceiveTaskCompletionSourceDict.Add(token, taskCompletionSource); } cancellationTokenSource ??= new CancellationTokenSource(API_PROVIDE_DIAGNOSIS_KEYS_TIMEOUT_MILLIS); DiagnosisKeysDataMapping diagnosisKeysDataMapping = configuration.GoogleDiagnosisKeysDataMappingConfig.ToDiagnosisKeysDataMapping(); try { DiagnosisKeysDataMapping currentDiagnosisKeysDataMapping = await enClient.GetDiagnosisKeysDataMappingAsync(); // https://github.com/google/exposure-notifications-internals/blob/aaada6ce5cad0ea1493930591557f8053ef4f113/exposurenotification/src/main/java/com/google/samples/exposurenotification/nearby/DiagnosisKeysDataMapping.java#L113 if (!diagnosisKeysDataMapping.Equals(currentDiagnosisKeysDataMapping)) { await enClient.SetDiagnosisKeysDataMappingAsync(diagnosisKeysDataMapping); await Handler.DiagnosisKeysDataMappingAppliedAsync(); Logger.I("DiagnosisKeysDataMapping have been updated."); } else { Logger.D("DiagnosisKeysDataMapping is not updated."); } var files = keyFiles.Select(f => new File(f)).ToList(); DiagnosisKeyFileProvider diagnosisKeyFileProvider = new DiagnosisKeyFileProvider(files); using (cancellationTokenSource.Token.Register(() => { Logger.D("ProvideDiagnosisKeysAsync cancellationTokenSource canceled."); taskCompletionSource?.TrySetException( new TimeoutException($"ExposureStateBroadcastReceiver was not called in {API_PROVIDE_DIAGNOSIS_KEYS_TIMEOUT_MILLIS} millis.") ); lock (ExposureStateBroadcastReceiveTaskCompletionSourceDict) { ExposureStateBroadcastReceiveTaskCompletionSourceDict.Remove(token); } })) { await enClient.ProvideDiagnosisKeysAsync(diagnosisKeyFileProvider); _ = await taskCompletionSource.Task; } Logger.D("ExposureStateBroadcastReceiveTaskCompletionSource is completed."); return(ProvideDiagnosisKeysResult.Completed); } catch (JavaTimeoutException exception) { // Wrap exception throw new TimeoutException(exception.Message); } catch (ApiException exception) { if (exception.IsENException()) { throw exception.ToENException(); } throw; } finally { lock (ExposureStateBroadcastReceiveTaskCompletionSourceDict) { ExposureStateBroadcastReceiveTaskCompletionSourceDict.Remove(token); } } }
public static void LogD(this NSErrorException nsErrorException) { Logger.D($"Error occurred {nsErrorException.Code} - {nsErrorException.Domain} - {nsErrorException.Message}"); }
public override bool OnStopJob(JobParameters @params) { Logger.E("ExposureNotDetectedJob stopped."); return(false); }
public override void OnReceive(Context context, Intent intent) { var action = intent.Action; Logger.D($"Intent Action {action}"); ExposureNotificationClient?enClient = null; if (context.ApplicationContext is IExposureNotificationHandler exposureNotificationHandler) { enClient = (ExposureNotificationClient)exposureNotificationHandler.GetEnClient(); } if (enClient is null) { Logger.E("ExposureStateBroadcastReceiver: enClient is null."); return; } try { switch (action) { case ACTION_EXPOSURE_STATE_UPDATED: Logger.D($"ACTION_EXPOSURE_STATE_UPDATED"); bool v1 = intent.HasExtra(EXTRA_EXPOSURE_SUMMARY); string varsionStr = v1 ? "1" : "2"; Logger.D($"EN version {varsionStr}"); if (v1) { string token = intent.GetStringExtra(EXTRA_TOKEN); ExposureDetectedV1Job.Enqueue( context, token, enClient.ExposureDetectedV1JobSetting ); } else { ExposureDetectedV2Job.Enqueue( context, enClient.ExposureDetectedV2JobSetting ); } break; case ACTION_EXPOSURE_NOT_FOUND: Logger.D($"ACTION_EXPOSURE_NOT_FOUND"); ExposureNotDetectedJob.Enqueue( context, enClient.ExposureNotDetectedJobSetting ); break; } } catch (Exception e) { Logger.E($"Exception occurred: {e}"); } finally { var exposureStateBroadcastReceiveTaskCompletionSourceDict = enClient.ExposureStateBroadcastReceiveTaskCompletionSourceDict; lock (exposureStateBroadcastReceiveTaskCompletionSourceDict) { foreach (var key in exposureStateBroadcastReceiveTaskCompletionSourceDict.Keys) { exposureStateBroadcastReceiveTaskCompletionSourceDict.TryGetValue(key, out var value); value?.TrySetResult(true); } } } }