/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.print.cts;

import static android.print.test.Utils.eventually;
import static android.print.test.Utils.runOnMainThread;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.inOrder;

import android.print.PrintAttributes;
import android.print.PrintAttributes.Margins;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Resolution;
import android.print.PrintDocumentAdapter;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.print.test.BasePrintTest;
import android.print.test.services.FirstPrintService;
import android.print.test.services.PrintServiceCallbacks;
import android.print.test.services.PrinterDiscoverySessionCallbacks;
import android.print.test.services.SecondPrintService;
import android.print.test.services.StubbablePrinterDiscoverySession;
import android.printservice.PrintJob;
import android.printservice.PrinterDiscoverySession;
import androidx.annotation.NonNull;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.exceptions.verification.VerificationInOrderFailure;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * This test verifies that the system respects the {@link PrinterDiscoverySession}
 * contract is respected.
 */
@RunWith(AndroidJUnit4.class)
public class PrinterDiscoverySessionLifecycleTest extends BasePrintTest {
    private static final String FIRST_PRINTER_LOCAL_ID = "first_printer";
    private static final String SECOND_PRINTER_LOCAL_ID = "second_printer";

    private static StubbablePrinterDiscoverySession sSession;

    @Before
    public void clearPrintSpoolerState() throws Exception {
        clearPrintSpoolerData();
    }

    /**
     * Add a printer to {@#sSession}.
     *
     * @param localId The id of the printer to add
     * @param hasCapabilities If the printer has capabilities
     */
    private void addPrinter(@NonNull String localId, boolean hasCapabilities) {
        // Add the first printer.
        PrinterId firstPrinterId = sSession.getService().generatePrinterId(
                localId);

        PrinterInfo.Builder printer = new PrinterInfo.Builder(firstPrinterId,
                localId, PrinterInfo.STATUS_IDLE);

        if (hasCapabilities) {
            printer.setCapabilities(new PrinterCapabilitiesInfo.Builder(firstPrinterId)
                    .setMinMargins(new Margins(200, 200, 200, 200))
                    .addMediaSize(MediaSize.ISO_A0, true)
                    .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
                    .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
                            PrintAttributes.COLOR_MODE_COLOR)
                    .build());
        }

        sSession.addPrinters(Collections.singletonList(printer.build()));
    }

    /**
     * Make {@code localPrinterId} the default printer. This requires a full print workflow.
     *
     * As a side-effect also approved the print service.
     *
     * @param localPrinterId The printer to make default
     */
    private void makeDefaultPrinter(String localPrinterId) throws Throwable {
        PrintDocumentAdapter adapter = createDefaultPrintDocumentAdapter(1);

        print(adapter);
        waitForWriteAdapterCallback(1);

        runOnMainThread(() -> addPrinter(localPrinterId, true));
        selectPrinter(localPrinterId);
        waitForWriteAdapterCallback(2);

        clickPrintButton();
        answerPrintServicesWarning(true);

        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
        resetCounters();
    }

    /**
     * Select a printer in the all printers activity
     *
     * @param printerName The name of the printer to select
     */
    private void selectInAllPrintersActivity(@NonNull String printerName) throws Exception {
        while (true) {
            UiObject printerItem = getUiDevice().findObject(
                    new UiSelector().text(printerName));

            if (printerItem.isEnabled()) {
                printerItem.click();
                break;
            } else {
                Thread.sleep(100);
            }
        }
    }

    @Test
    public void defaultPrinterBecomesAvailableWhileInBackground() throws Throwable {
        // Create the session callbacks that we will be checking.
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createMockPrinterDiscoverySessionCallbacks(invocation -> {
                    sSession =
                            ((PrinterDiscoverySessionCallbacks) invocation.getMock()).getSession();

                    onPrinterDiscoverySessionCreateCalled();
                    return null;
                }, null, null, null, null, null, invocation -> {
                    onPrinterDiscoverySessionDestroyCalled();
                    return null;
                });

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks, null, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());

        makeDefaultPrinter(FIRST_PRINTER_LOCAL_ID);

        PrintDocumentAdapter adapter = createDefaultPrintDocumentAdapter(1);
        print(adapter);
        waitForPrinterDiscoverySessionCreateCallbackCalled();

        waitForPrinterUnavailable();

        selectPrinter("All printers…");
        // Let all printers activity start
        Thread.sleep(500);

        // Add printer
        runOnMainThread(() -> addPrinter(FIRST_PRINTER_LOCAL_ID, true));

        // Select printer once available (this returns to main print activity)
        selectInAllPrintersActivity(FIRST_PRINTER_LOCAL_ID);

        // Wait for preview to load and finish print
        waitForWriteAdapterCallback(1);
        clickPrintButton();
        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
    }

    @Test
    public void defaultPrinterBecomesUsableWhileInBackground() throws Throwable {
        // Create the session callbacks that we will be checking.
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createMockPrinterDiscoverySessionCallbacks(invocation -> {
                    sSession =
                            ((PrinterDiscoverySessionCallbacks) invocation.getMock()).getSession();

                    onPrinterDiscoverySessionCreateCalled();
                    return null;
                }, null, null, null, null, null, invocation -> {
                    onPrinterDiscoverySessionDestroyCalled();
                    return null;
                });

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks, null, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());

        makeDefaultPrinter(FIRST_PRINTER_LOCAL_ID);

        PrintDocumentAdapter adapter = createDefaultPrintDocumentAdapter(1);
        print(adapter);
        waitForPrinterDiscoverySessionCreateCallbackCalled();

        // Add printer but do not enable it (capabilities == null)
        runOnMainThread(() -> addPrinter(FIRST_PRINTER_LOCAL_ID, false));
        waitForPrinterUnavailable();

        selectPrinter("All printers…");
        // Let all printers activity start
        Thread.sleep(500);

        // Enable printer
        runOnMainThread(() -> addPrinter(FIRST_PRINTER_LOCAL_ID, true));

        // Select printer once available (this returns to main print activity)
        selectInAllPrintersActivity(FIRST_PRINTER_LOCAL_ID);

        // Wait for preview to load and finish print
        waitForWriteAdapterCallback(1);
        clickPrintButton();
        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
    }

    @Test
    public void normalLifecycle() throws Throwable {
        // Create the session callbacks that we will be checking.
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createFirstMockPrinterDiscoverySessionCallbacks();

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks,
                invocation -> {
                    PrintJob printJob = (PrintJob) invocation.getArguments()[0];
                    // We pretend the job is handled immediately.
                    printJob.complete();
                    return null;
                }, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());

        // Create a print adapter that respects the print contract.
        PrintDocumentAdapter adapter = createDefaultPrintDocumentAdapter(1);

        // Start printing.
        print(adapter);

        // Wait for write of the first page.
        waitForWriteAdapterCallback(1);

        runOnMainThread(() -> assertFalse(sSession.isDestroyed()));
        runOnMainThread(() -> assertEquals(0, sSession.getTrackedPrinters().size()));

        // Select the first printer.
        selectPrinter(FIRST_PRINTER_LOCAL_ID);

        eventually(() -> runOnMainThread(() -> assertEquals(FIRST_PRINTER_LOCAL_ID,
                sSession.getTrackedPrinters().get(0).getLocalId())));
        runOnMainThread(() -> assertTrue(sSession.isPrinterDiscoveryStarted()));
        runOnMainThread(() -> assertEquals(1, sSession.getTrackedPrinters().size()));

        // Wait for layout as the printer has different capabilities.
        waitForLayoutAdapterCallbackCount(2);

        // Select the second printer (same capabilities as the other
        // one so no layout should happen).
        selectPrinter(SECOND_PRINTER_LOCAL_ID);

        eventually(() -> runOnMainThread(() -> assertEquals(SECOND_PRINTER_LOCAL_ID,
                sSession.getTrackedPrinters().get(0).getLocalId())));
        runOnMainThread(() -> assertEquals(1, sSession.getTrackedPrinters().size()));

        // While the printer discovery session is still alive store the
        // ids of printers as we want to make some assertions about them
        // but only the print service can create printer ids which means
        // that we need to get the created ones.
        PrinterId firstPrinterId = getAddedPrinterIdForLocalId(
                FIRST_PRINTER_LOCAL_ID);
        PrinterId secondPrinterId = getAddedPrinterIdForLocalId(
                SECOND_PRINTER_LOCAL_ID);
        assertNotNull("Coundn't find printer:" + FIRST_PRINTER_LOCAL_ID, firstPrinterId);
        assertNotNull("Coundn't find printer:" + SECOND_PRINTER_LOCAL_ID, secondPrinterId);

        // Click the print button.
        clickPrintButton();

        // Answer the dialog for the print service cloud warning
        answerPrintServicesWarning(true);

        // Wait for all print jobs to be handled after which the session destroyed.
        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);

        runOnMainThread(() -> assertTrue(sSession.isDestroyed()));
        runOnMainThread(() -> assertFalse(sSession.isPrinterDiscoveryStarted()));
        runOnMainThread(() -> assertEquals(0, sSession.getTrackedPrinters().size()));

        // Verify the expected calls.
        InOrder inOrder = inOrder(firstSessionCallbacks);

        // We start discovery as the print dialog was up.
        List<PrinterId> emptyPrinterIdList = Collections.emptyList();
        inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(
                emptyPrinterIdList);

        // We selected the first printer and now it should be tracked.
        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
                firstPrinterId);

        // We selected the second printer so the first should not be tracked.
        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
                firstPrinterId);

        // We selected the second printer and now it should be tracked.
        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
                secondPrinterId);

        // The print dialog went away so we first stop the printer tracking...
        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
                secondPrinterId);

        // ... next we stop printer discovery...
        inOrder.verify(firstSessionCallbacks).onStopPrinterDiscovery();

        // ... last the session is destroyed.
        inOrder.verify(firstSessionCallbacks).onDestroy();
    }

    @Test
    public void cancelPrintServicesAlertDialog() throws Throwable {
        // Create the session callbacks that we will be checking.
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createFirstMockPrinterDiscoverySessionCallbacks();

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks,
                invocation -> {
                    PrintJob printJob = (PrintJob) invocation.getArguments()[0];
                    // We pretend the job is handled immediately.
                    printJob.complete();
                    return null;
                }, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());

        // Create a print adapter that respects the print contract.
        PrintDocumentAdapter adapter = createDefaultPrintDocumentAdapter(1);

        // Start printing.
        print(adapter);

        // Wait for write of the first page.
        waitForWriteAdapterCallback(1);

        runOnMainThread(() -> assertFalse(sSession.isDestroyed()));
        runOnMainThread(() -> assertEquals(0, sSession.getTrackedPrinters().size()));

        // Select the first printer.
        selectPrinter(FIRST_PRINTER_LOCAL_ID);

        eventually(() -> runOnMainThread(() -> assertEquals(FIRST_PRINTER_LOCAL_ID,
                sSession.getTrackedPrinters().get(0).getLocalId())));
        runOnMainThread(() -> assertTrue(sSession.isPrinterDiscoveryStarted()));
        runOnMainThread(() -> assertEquals(1, sSession.getTrackedPrinters().size()));

        // While the printer discovery session is still alive store the
        // ids of printers as we want to make some assertions about them
        // but only the print service can create printer ids which means
        // that we need to get the created ones.
        PrinterId firstPrinterId = getAddedPrinterIdForLocalId(
                FIRST_PRINTER_LOCAL_ID);
        assertNotNull("Coundn't find printer:" + FIRST_PRINTER_LOCAL_ID, firstPrinterId);

        // Click the print button.
        clickPrintButton();

        // Cancel the dialog for the print service cloud warning
        answerPrintServicesWarning(false);

        // Click the print button again.
        clickPrintButton();

        // Answer the dialog for the print service cloud warning
        answerPrintServicesWarning(true);

        // Wait for all print jobs to be handled after which the session destroyed.
        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);

        runOnMainThread(() -> assertTrue(sSession.isDestroyed()));
        runOnMainThread(() -> assertFalse(sSession.isPrinterDiscoveryStarted()));
        runOnMainThread(() -> assertEquals(0, sSession.getTrackedPrinters().size()));

        // Verify the expected calls.
        InOrder inOrder = inOrder(firstSessionCallbacks);

        // We start discovery as the print dialog was up.
        List<PrinterId> emptyPrinterIdList = Collections.emptyList();
        inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(
                emptyPrinterIdList);

        // We selected the first printer and now it should be tracked.
        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
                firstPrinterId);

        // We selected the second printer so the first should not be tracked.
        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
                firstPrinterId);

        // ... next we stop printer discovery...
        inOrder.verify(firstSessionCallbacks).onStopPrinterDiscovery();

        // ... last the session is destroyed.
        inOrder.verify(firstSessionCallbacks).onDestroy();
    }

    @Test
    public void startPrinterDiscoveryWithHistoricalPrinters() throws Throwable {
        // Create the session callbacks that we will be checking.
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createFirstMockPrinterDiscoverySessionCallbacks();

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks,
                invocation -> {
                    PrintJob printJob = (PrintJob) invocation.getArguments()[0];
                    // We pretend the job is handled immediately.
                    printJob.complete();
                    return null;
                }, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());

        // Create a print adapter that respects the print contract.
        PrintDocumentAdapter adapter = createDefaultPrintDocumentAdapter(1);

        // Start printing.
        print(adapter);

        // Wait for write of the first page.
        waitForWriteAdapterCallback(1);

        runOnMainThread(() -> assertFalse(sSession.isDestroyed()));
        runOnMainThread(() -> assertEquals(0, sSession.getTrackedPrinters().size()));

        // Select the first printer.
        selectPrinter(FIRST_PRINTER_LOCAL_ID);

        eventually(() -> runOnMainThread(() -> assertEquals(FIRST_PRINTER_LOCAL_ID,
                sSession.getTrackedPrinters().get(0).getLocalId())));
        runOnMainThread(() -> assertTrue(sSession.isPrinterDiscoveryStarted()));
        runOnMainThread(() -> assertEquals(1, sSession.getTrackedPrinters().size()));

        // Wait for a layout to finish - first layout was for the
        // PDF printer, second for the first printer in preview mode.
        waitForLayoutAdapterCallbackCount(2);

        // While the printer discovery session is still alive store the
        // ids of printer as we want to make some assertions about it
        // but only the print service can create printer ids which means
        // that we need to get the created one.
        PrinterId firstPrinterId = getAddedPrinterIdForLocalId(
                FIRST_PRINTER_LOCAL_ID);

        // Click the print button.
        clickPrintButton();

        // Answer the dialog for the print service cloud warning
        answerPrintServicesWarning(true);

        // Wait for the print to complete.
        waitForAdapterFinishCallbackCalled();

        // Now print again as we want to confirm that the start
        // printer discovery passes in the priority list.
        print(adapter);

        // Wait for a layout to finish - first layout was for the
        // PDF printer, second for the first printer in preview mode,
        // the third for the first printer in non-preview mode, and
        // now a fourth for the PDF printer as we are printing again.
        waitForLayoutAdapterCallbackCount(4);

        // Cancel the printing.
        getUiDevice().pressBack(); // wakes up the device.
        getUiDevice().pressBack();

        // Wait for all print jobs to be handled after which the is session destroyed.
        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);

        runOnMainThread(() -> assertTrue(sSession.isDestroyed()));
        runOnMainThread(() -> assertFalse(sSession.isPrinterDiscoveryStarted()));
        runOnMainThread(() -> assertEquals(0, sSession.getTrackedPrinters().size()));

        // Verify the expected calls.
        InOrder inOrder = inOrder(firstSessionCallbacks);

        // We start discovery with no printer history.
        List<PrinterId> priorityList = new ArrayList<>();
        inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(
                priorityList);

        // We selected the first printer and now it should be tracked.
        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
                firstPrinterId);

        // We confirmed print so the first should not be tracked.
        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
                firstPrinterId);

        // This is tricky. It is possible that the print activity was not
        // destroyed (the platform delays destruction at convenient time as
        // an optimization) and we get the same instance which means that
        // the discovery session may not have been destroyed. We try the
        // case with the activity being destroyed and if this fails the
        // case with the activity brought to front.
        priorityList.add(firstPrinterId);
        try {
            inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(priorityList);
        } catch (VerificationInOrderFailure error) {
            inOrder.verify(firstSessionCallbacks).onValidatePrinters(priorityList);
        }

        // The system selects the highest ranked historical printer.
        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
                firstPrinterId);

        // We canceled print so the first should not be tracked.
        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
                firstPrinterId);


        // Discovery is always stopped before the session is always destroyed.
        inOrder.verify(firstSessionCallbacks).onStopPrinterDiscovery();

        // ...last the session is destroyed.
        inOrder.verify(firstSessionCallbacks).onDestroy();
    }

    @Test
    public void addRemovePrinters() throws Throwable {
        StubbablePrinterDiscoverySession[] session = new StubbablePrinterDiscoverySession[1];

        // Create the session callbacks that we will be checking.
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createMockPrinterDiscoverySessionCallbacks(invocation -> {
                    session[0] = ((PrinterDiscoverySessionCallbacks)
                            invocation.getMock()).getSession();

                    onPrinterDiscoverySessionCreateCalled();
                    return null;
                }, null, null, null, null, null, invocation -> {
                    onPrinterDiscoverySessionDestroyCalled();
                    return null;
                });

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks, null, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());

        print(createDefaultPrintDocumentAdapter(1));

        waitForPrinterDiscoverySessionCreateCallbackCalled();

        runOnMainThread(() -> assertEquals(0, session[0].getPrinters().size()));

        PrinterId[] printerIds = new PrinterId[3];
        runOnMainThread(() -> {
            printerIds[0] = session[0].getService().generatePrinterId("0");
            printerIds[1] = session[0].getService().generatePrinterId("1");
            printerIds[2] = session[0].getService().generatePrinterId("2");
        });

        PrinterInfo printer1 = (new PrinterInfo.Builder(printerIds[0], "0",
                PrinterInfo.STATUS_IDLE)).build();

        PrinterInfo printer2 = (new PrinterInfo.Builder(printerIds[1], "1",
                PrinterInfo.STATUS_IDLE)).build();

        PrinterInfo printer3 = (new PrinterInfo.Builder(printerIds[2], "2",
                PrinterInfo.STATUS_IDLE)).build();

        ArrayList<PrinterInfo> printers = new ArrayList<>();
        printers.add(printer1);
        runOnMainThread(() -> session[0].addPrinters(printers));
        eventually(() -> runOnMainThread(() -> assertEquals(1, session[0].getPrinters().size())));

        printers.add(printer2);
        printers.add(printer3);
        runOnMainThread(() -> session[0].addPrinters(printers));
        eventually(() -> runOnMainThread(() -> assertEquals(3, session[0].getPrinters().size())));

        ArrayList<PrinterId> printerIdsToRemove = new ArrayList<>();
        printerIdsToRemove.add(printer1.getId());
        runOnMainThread(() -> session[0].removePrinters(printerIdsToRemove));
        eventually(() -> runOnMainThread(() -> assertEquals(2, session[0].getPrinters().size())));

        printerIdsToRemove.add(printer2.getId());
        printerIdsToRemove.add(printer3.getId());
        runOnMainThread(() -> session[0].removePrinters(printerIdsToRemove));
        eventually(() -> runOnMainThread(() -> assertEquals(0, session[0].getPrinters().size())));

        getUiDevice().pressBack();

        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
    }

    private PrinterId getAddedPrinterIdForLocalId(String printerLocalId) throws Throwable {
        final List<PrinterInfo> reportedPrinters = new ArrayList<>();
        runOnMainThread(() -> {
            // Grab the printer ids as only the service can create such.
            reportedPrinters.addAll(sSession.getPrinters());
        });

        final int reportedPrinterCount = reportedPrinters.size();
        for (int i = 0; i < reportedPrinterCount; i++) {
            PrinterInfo reportedPrinter = reportedPrinters.get(i);
            String localId = reportedPrinter.getId().getLocalId();
            if (printerLocalId.equals(localId)) {
                return reportedPrinter.getId();
            }
        }

        return null;
    }

    private PrintServiceCallbacks createSecondMockPrintServiceCallbacks() {
        return createMockPrintServiceCallbacks(null, null, null);
    }

    private PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
        return createMockPrinterDiscoverySessionCallbacks(invocation -> {
            // Get the session.
            sSession = ((PrinterDiscoverySessionCallbacks)
                    invocation.getMock()).getSession();

            assertTrue(sSession.isPrinterDiscoveryStarted());

            addPrinter(FIRST_PRINTER_LOCAL_ID, false);
            addPrinter(SECOND_PRINTER_LOCAL_ID, false);

            return null;
        }, invocation -> {
            assertFalse(sSession.isPrinterDiscoveryStarted());
            return null;
        }, null, invocation -> {
            // Get the session.
            StubbablePrinterDiscoverySession session = ((PrinterDiscoverySessionCallbacks)
                    invocation.getMock()).getSession();

            PrinterId trackedPrinterId = (PrinterId) invocation.getArguments()[0];
            List<PrinterInfo> reportedPrinters = session.getPrinters();

            // We should be tracking a printer that we added.
            PrinterInfo trackedPrinter = null;
            final int reportedPrinterCount = reportedPrinters.size();
            for (int i = 0; i < reportedPrinterCount; i++) {
                PrinterInfo reportedPrinter = reportedPrinters.get(i);
                if (reportedPrinter.getId().equals(trackedPrinterId)) {
                    trackedPrinter = reportedPrinter;
                    break;
                }
            }
            assertNotNull("Can track only added printers", trackedPrinter);

            assertTrue(sSession.getTrackedPrinters().contains(trackedPrinter.getId()));
            assertEquals(1, sSession.getTrackedPrinters().size());

            // If the printer does not have capabilities reported add them.
            if (trackedPrinter.getCapabilities() == null) {

                // Add the capabilities to emulate lazy discovery.
                // Same for each printer is fine for what we test.
                PrinterCapabilitiesInfo capabilities =
                        new PrinterCapabilitiesInfo.Builder(trackedPrinterId)
                                .setMinMargins(new Margins(200, 200, 200, 200))
                                .addMediaSize(MediaSize.ISO_A4, true)
                                .addMediaSize(MediaSize.ISO_A5, false)
                                .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
                                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
                                        PrintAttributes.COLOR_MODE_COLOR)
                                .build();
                PrinterInfo updatedPrinter = new PrinterInfo.Builder(trackedPrinter)
                        .setCapabilities(capabilities)
                        .build();

                // Update the printer.
                List<PrinterInfo> printers = new ArrayList<>();
                printers.add(updatedPrinter);
                session.addPrinters(printers);
            }

            return null;
        }, null, null, invocation -> {
            assertTrue(sSession.isDestroyed());

            // Take a note onDestroy was called.
            onPrinterDiscoverySessionDestroyCalled();
            return null;
        });
    }
}
