Source:
<code>void notify(@NonNull Error error, @NonNull DeliveryStyle style, @Nullable Callback callback) { if (error.shouldIgnoreClass()) { return; } Map<String, Object> errorAppData = appData.getAppData(); String releaseStage = getStringFromMap("releaseStage", errorAppData); if (!config.shouldNotifyForReleaseStage(releaseStage)) { return; } Map<String, Object> errorDeviceData = deviceData.getDeviceData(); error.setDeviceData(errorDeviceData); error.getMetaData().store.put("device", deviceData.getDeviceMetaData()); error.setAppData(errorAppData); error.getMetaData().store.put("app", appData.getAppDataMetaData()); error.setBreadcrumbs(breadcrumbs); error.setUser(user); if (TextUtils.isEmpty(error.getContext())) { String context = config.getContext(); error.setContext(context != null ? context : appData.getActiveScreenClass()); } if (!runBeforeNotifyTasks(error)) { Logger.info("Skipping notification - beforeNotify task returned false"); return; } Report report = new Report(config.getApiKey(), error); if (callback != null) { callback.beforeNotify(report); } if (sessionTracker.getCurrentSession() != null) { setChanged(); <START> notifyObservers(new NativeInterface.Message( <END> NativeInterface.MessageType.NOTIFY_HANDLED, error.getExceptionName())); } switch (style) { case SAME_THREAD: deliver(report, error); break; case ASYNC: final Report finalReport = report; final Error finalError = error; try { Async.run(new Runnable() { @Override public void run() { deliver(finalReport, finalError); } }); } catch (RejectedExecutionException exception) { errorStore.write(error); Logger.warn("Exceeded max queue count, saving to disk to send later"); } break; case ASYNC_WITH_CACHE: errorStore.write(error); errorStore.flushAsync(); break; default: break; } }</code><technical_language>previously notify observers for handled errors (presumably of unpredictable behaviour unhandled error?)</technical_language>

Target:
void notify(@NonNull Error error, @NonNull DeliveryStyle style, @Nullable Callback callback) { if (error.shouldIgnoreClass()) { return; } Map<String, Object> errorAppData = appData.getAppData(); String releaseStage = getStringFromMap("releaseStage", errorAppData); if (!config.shouldNotifyForReleaseStage(releaseStage)) { return; } Map<String, Object> errorDeviceData = deviceData.getDeviceData(); error.setDeviceData(errorDeviceData); error.getMetaData().store.put("device", deviceData.getDeviceMetaData()); error.setAppData(errorAppData); error.getMetaData().store.put("app", appData.getAppDataMetaData()); error.setBreadcrumbs(breadcrumbs); error.setUser(user); if (TextUtils.isEmpty(error.getContext())) { String context = config.getContext(); error.setContext(context != null ? context : appData.getActiveScreenClass()); } if (!runBeforeNotifyTasks(error)) { Logger.info("Skipping notification - beforeNotify task returned false"); return; } Report report = new Report(config.getApiKey(), error); if (callback != null) { callback.beforeNotify(report); } if (!error.getHandledState().isUnhandled() && error.getSession() != null) { setChanged(); notifyObservers(new NativeInterface.Message( NativeInterface.MessageType.NOTIFY_HANDLED, error.getExceptionName())); } switch (style) { case SAME_THREAD: deliver(report, error); break; case ASYNC: final Report finalReport = report; final Error finalError = error; try { Async.run(new Runnable() { @Override public void run() { deliver(finalReport, finalError); } }); } catch (RejectedExecutionException exception) { errorStore.write(error); Logger.warn("Exceeded max queue count, saving to disk to send later"); } break; case ASYNC_WITH_CACHE: errorStore.write(error); errorStore.flushAsync(); break; default: break; } }