Crashes extends AbstractAppCenterService { @Override protected Channel.GroupListener getChannelListener() { return new Channel.GroupListener() { private void processCallback(final Log log, final CallbackProcessor callbackProcessor) { post(new Runnable() { @Override public void run() { if (log instanceof ManagedErrorLog) { ManagedErrorLog errorLog = (ManagedErrorLog) log; final ErrorReport report = buildErrorReport(errorLog); UUID id = errorLog.getId(); if (report != null) { if (callbackProcessor.shouldDeleteThrowable()) { removeStoredThrowable(id); } HandlerUtils.runOnUiThread(new Runnable() { @Override public void run() { callbackProcessor.onCallBack(report); } }); } else { AppCenterLog.warn(LOG_TAG, "Cannot find crash report for the error log: " + id); } } else if (!(log instanceof ErrorAttachmentLog) && !(log instanceof HandledErrorLog)) { AppCenterLog.warn(LOG_TAG, "A different type of log comes to crashes: " + log.getClass().getName()); } } }); } @Override public void onBeforeSending(Log log) { processCallback(log, new CallbackProcessor() { @Override public boolean shouldDeleteThrowable() { return false; } @Override public void onCallBack(ErrorReport report) { mCrashesListener.onBeforeSending(report); } }); } @Override public void onSuccess(Log log) { processCallback(log, new CallbackProcessor() { @Override public boolean shouldDeleteThrowable() { return true; } @Override public void onCallBack(ErrorReport report) { mCrashesListener.onSendingSucceeded(report); } }); } @Override public void onFailure(Log log, final java.lang.Exception e) { processCallback(log, new CallbackProcessor() { @Override public boolean shouldDeleteThrowable() { return true; } @Override public void onCallBack(ErrorReport report) { mCrashesListener.onSendingFailed(report, e); } }); } }; } private  Crashes(); @NonNull static synchronized Crashes getInstance(); static AppCenterFuture<Boolean> isEnabled(); static AppCenterFuture<Void> setEnabled(boolean enabled); @SuppressWarnings({"SameParameterValue", "WeakerAccess"}) static void trackError(Throwable throwable); static void trackError(Throwable throwable, Map<String, String> properties, Iterable<ErrorAttachmentLog> attachments); static void generateTestCrash(); static void setListener(CrashesListener listener); static AppCenterFuture<String> getMinidumpDirectory(); static void notifyUserConfirmation(@UserConfirmationDef int userConfirmation); static AppCenterFuture<Boolean> hasCrashedInLastSession(); static AppCenterFuture<ErrorReport> getLastSessionCrashReport(); static AppCenterFuture<Boolean> hasReceivedMemoryWarningInLastSession(); @Override synchronized void onStarted(@NonNull Context context, @NonNull Channel channel, String appSecret, String transmissionTargetToken, boolean startedFromApp); @Override Map<String, LogFactory> getLogFactories(); @Override String getServiceName(); static final int SEND; static final int DONT_SEND; static final int ALWAYS_SEND; @VisibleForTesting
    static final String PREF_KEY_ALWAYS_SEND; static final String LOG_TAG; }
@Test public void getChannelListener() throws JSONException { ErrorReport errorReport = ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, STACK_TRACE); mockStatic(ErrorLogHelper.class); File errorLogFile = mock(File.class); when(errorLogFile.length()).thenReturn(1L); when(ErrorLogHelper.getLastErrorLogFile()).thenReturn(errorLogFile); when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[]{mock(File.class)}); when(ErrorLogHelper.getNewMinidumpFiles()).thenReturn(new File[0]); File throwableFile = mock(File.class); when(throwableFile.length()).thenReturn(1L); when(ErrorLogHelper.getStoredThrowableFile(any(UUID.class))).thenReturn(throwableFile); when(ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, STACK_TRACE)).thenReturn(errorReport); when(FileManager.read(any(File.class))).thenReturn(""); when(FileManager.read(any(File.class))).thenReturn(STACK_TRACE); LogSerializer logSerializer = mock(LogSerializer.class); when(logSerializer.deserializeLog(anyString(), anyString())).thenReturn(mErrorLog); CrashesListener crashesListener = mock(CrashesListener.class); when(crashesListener.shouldProcess(any(ErrorReport.class))).thenReturn(true); Crashes.setListener(crashesListener); Crashes crashes = Crashes.getInstance(); crashes.setLogSerializer(logSerializer); crashes.onStarting(mAppCenterHandler); crashes.onStarted(mock(Context.class), mock(Channel.class), "", null, true); verifyStatic(); ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, STACK_TRACE); assertNull(errorReport.getDevice()); mErrorLog.setDevice(mock(Device.class)); ArgumentCaptor<ErrorReport> errorReportCaptor = ArgumentCaptor.forClass(ErrorReport.class); Channel.GroupListener channelListener = crashes.getChannelListener(); channelListener.onBeforeSending(mErrorLog); verify(crashesListener).onBeforeSending(errorReportCaptor.capture()); assertErrorEquals(mErrorLog, errorReportCaptor.getValue()); channelListener.onSuccess(mErrorLog); verify(crashesListener).onSendingSucceeded(errorReportCaptor.capture()); assertErrorEquals(mErrorLog, errorReportCaptor.getValue()); verifyStatic(); ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, STACK_TRACE); channelListener.onFailure(mErrorLog, EXCEPTION); verify(crashesListener).onSendingFailed(errorReportCaptor.capture(), eq(EXCEPTION)); assertErrorEquals(mErrorLog, errorReportCaptor.getValue()); verifyStatic(times(2)); ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, STACK_TRACE); }