blob: 8ec44fe71cfcc0e3a349ffc6ec83e8ffcc706bff [file] [log] [blame]
/*
* Copyright (C) 2016 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.getPrintJob;
import static android.print.test.Utils.getPrintManager;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintJob;
import android.print.PrintJobInfo;
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.support.test.runner.AndroidJUnit4;
import android.util.Log;
import androidx.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
/**
* Test interface from the application to the print service.
*/
@RunWith(AndroidJUnit4.class)
public class InterfaceForAppsTest extends BasePrintTest {
private static final String TEST_PRINTER = "Test printer";
private static final String LOG_TAG = "InterfaceForAppsTest";
private static final PrintAttributes.Resolution TWO_HUNDRED_DPI =
new PrintAttributes.Resolution("200x200", "200dpi", 200, 200);
private static boolean sHasBeenSetUp;
/**
* Create a mock {@link PrinterDiscoverySessionCallbacks} that discovers a simple test printer.
*
* @return The mock session callbacks
*/
private @NonNull PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
return createMockPrinterDiscoverySessionCallbacks(invocation -> {
StubbablePrinterDiscoverySession session = ((PrinterDiscoverySessionCallbacks) invocation
.getMock()).getSession();
if (session.getPrinters().isEmpty()) {
PrinterId printerId = session.getService().generatePrinterId(TEST_PRINTER);
PrinterInfo.Builder printer = new PrinterInfo.Builder(
session.getService().generatePrinterId(TEST_PRINTER), TEST_PRINTER,
PrinterInfo.STATUS_IDLE);
printer.setCapabilities(new PrinterCapabilitiesInfo.Builder(printerId)
.addMediaSize(PrintAttributes.MediaSize.ISO_A5, true)
.addMediaSize(PrintAttributes.MediaSize.ISO_A3, false)
.addResolution(TWO_HUNDRED_DPI, true)
.setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME
| PrintAttributes.COLOR_MODE_COLOR,
PrintAttributes.COLOR_MODE_MONOCHROME)
.setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE
| PrintAttributes.DUPLEX_MODE_LONG_EDGE,
PrintAttributes.DUPLEX_MODE_NONE)
.setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0)).build());
ArrayList<PrinterInfo> printers = new ArrayList<>(1);
printers.add(printer.build());
session.addPrinters(printers);
}
return null;
}, null, null, invocation -> null, null, null, invocation -> {
// Take a note onDestroy was called.
onPrinterDiscoverySessionDestroyCalled();
return null;
});
}
/**
* Create mock service callback for a session. Once the job is queued the test function is
* called.
*
* @param sessionCallbacks The callbacks of the session
* @param blockAfterState The state the print services should progress to
*/
private @NonNull PrintServiceCallbacks createFirstMockPrinterServiceCallbacks(
final @NonNull PrinterDiscoverySessionCallbacks sessionCallbacks, int blockAfterState) {
return createMockPrintServiceCallbacks(
invocation -> sessionCallbacks, invocation -> {
android.printservice.PrintJob job = (android.printservice.PrintJob) invocation
.getArguments()[0];
switch (blockAfterState) {
case PrintJobInfo.STATE_CREATED:
eventually(() -> assertEquals(PrintJobInfo.STATE_CREATED,
job.getInfo().getState()));
break;
case PrintJobInfo.STATE_STARTED:
eventually(() -> assertTrue(job.isQueued()));
job.start();
break;
case PrintJobInfo.STATE_QUEUED:
eventually(() -> assertTrue(job.isQueued()));
break;
case PrintJobInfo.STATE_BLOCKED:
eventually(() -> assertTrue(job.isQueued()));
job.start();
job.block("test block");
break;
case PrintJobInfo.STATE_FAILED:
eventually(() -> assertTrue(job.isQueued()));
job.start();
job.fail("test fail");
break;
case PrintJobInfo.STATE_COMPLETED:
eventually(() -> assertTrue(job.isQueued()));
job.start();
job.complete();
break;
default:
throw new Exception("Should not be reached");
}
return null;
}, invocation -> {
android.printservice.PrintJob job = (android.printservice.PrintJob) invocation
.getArguments()[0];
job.cancel();
Log.d(LOG_TAG, "job.cancel()");
return null;
});
}
/**
* Setup mock print subsystem
*
* @param blockAfterState Tell the print service to block all print jobs at this state
*
* @return The print document adapter to be used for printing
*/
private @NonNull PrintDocumentAdapter setupPrint(int blockAfterState) {
// Create the session of the printers that we will be checking.
PrinterDiscoverySessionCallbacks sessionCallbacks = createFirstMockPrinterDiscoverySessionCallbacks();
// Create the service callbacks for the first print service.
PrintServiceCallbacks serviceCallbacks = createFirstMockPrinterServiceCallbacks(
sessionCallbacks, blockAfterState);
// Configure the print services.
FirstPrintService.setCallbacks(serviceCallbacks);
// We don't use the second service, but we have to still configure it
SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
return createDefaultPrintDocumentAdapter(1);
}
@Before
public void setPrinter() throws Exception {
if (!sHasBeenSetUp) {
resetCounters();
PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_COMPLETED);
makeDefaultPrinter(adapter, TEST_PRINTER);
sHasBeenSetUp = true;
}
resetCounters();
}
/**
* Base test for all cancel print job tests
*
* @param cancelAfterState The print job state state to progress to canceling
* @param printJobName The print job name to use
*
* @throws Exception If anything is unexpected
*/
private void cancelPrintJobBaseTest(int cancelAfterState, @NonNull String printJobName)
throws Throwable {
PrintDocumentAdapter adapter = setupPrint(cancelAfterState);
print(adapter, printJobName);
waitForWriteAdapterCallback(1);
clickPrintButton();
PrintJob job = getPrintJob(getPrintManager(getActivity()), printJobName);
// Check getState
eventually(() -> assertEquals(cancelAfterState, job.getInfo().getState()));
// Check
switch (cancelAfterState) {
case PrintJobInfo.STATE_QUEUED:
assertTrue(job.isQueued());
break;
case PrintJobInfo.STATE_STARTED:
assertTrue(job.isStarted());
break;
case PrintJobInfo.STATE_BLOCKED:
assertTrue(job.isBlocked());
break;
case PrintJobInfo.STATE_COMPLETED:
assertTrue(job.isCompleted());
break;
case PrintJobInfo.STATE_FAILED:
assertTrue(job.isFailed());
break;
case PrintJobInfo.STATE_CANCELED:
assertTrue(job.isCancelled());
break;
}
job.cancel();
eventually(() -> assertTrue(job.isCancelled()));
waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
}
@Test
public void attemptCancelCreatedPrintJob() throws Throwable {
PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_STARTED);
print(adapter, "testAttemptCancelCreatedPrintJob");
waitForWriteAdapterCallback(1);
PrintJob job = getPrintJob(getPrintManager(getActivity()),
"testAttemptCancelCreatedPrintJob");
// Cancel does not have an effect on created jobs
job.cancel();
eventually(() -> assertEquals(PrintJobInfo.STATE_CREATED, job.getInfo().getState()));
// Cancel printing by exiting print activity
getUiDevice().pressBack();
eventually(() -> assertTrue(job.isCancelled()));
waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
}
@Test
public void cancelStartedPrintJob() throws Throwable {
cancelPrintJobBaseTest(PrintJobInfo.STATE_STARTED, "testCancelStartedPrintJob");
}
@Test
public void cancelBlockedPrintJob() throws Throwable {
cancelPrintJobBaseTest(PrintJobInfo.STATE_BLOCKED, "testCancelBlockedPrintJob");
}
@Test
public void cancelFailedPrintJob() throws Throwable {
cancelPrintJobBaseTest(PrintJobInfo.STATE_FAILED, "testCancelFailedPrintJob");
}
@Test
public void restartFailedPrintJob() throws Throwable {
PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_FAILED);
print(adapter, "testRestartFailedPrintJob");
waitForWriteAdapterCallback(1);
clickPrintButton();
PrintJob job = getPrintJob(getPrintManager(getActivity()), "testRestartFailedPrintJob");
eventually(() -> assertTrue(job.isFailed()));
// Restart goes from failed right to queued, so stop the print job at "queued" now
setupPrint(PrintJobInfo.STATE_QUEUED);
job.restart();
eventually(() -> assertTrue(job.isQueued()));
job.cancel();
eventually(() -> assertTrue(job.isCancelled()));
waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
}
@Test
public void getTwoPrintJobStates() throws Throwable {
PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_BLOCKED);
print(adapter, "testGetTwoPrintJobStates-block");
waitForWriteAdapterCallback(1);
clickPrintButton();
waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
PrintJob job1 = getPrintJob(getPrintManager(getActivity()),
"testGetTwoPrintJobStates-block");
eventually(() -> assertTrue(job1.isBlocked()));
adapter = setupPrint(PrintJobInfo.STATE_COMPLETED);
print(adapter, "testGetTwoPrintJobStates-complete");
waitForWriteAdapterCallback(2);
clickPrintButton();
PrintJob job2 = getPrintJob(getPrintManager(getActivity()),
"testGetTwoPrintJobStates-complete");
eventually(() -> assertTrue(job2.isCompleted()));
// Ids have to be unique
assertFalse(job1.getId().equals(job2.getId()));
assertFalse(job1.equals(job2));
// Ids have to be the same in job and info and if we find the same job again
assertEquals(job1.getId(), job1.getInfo().getId());
assertEquals(job1.getId(),
getPrintJob(getPrintManager(getActivity()),
"testGetTwoPrintJobStates-block").getId());
assertEquals(job1, getPrintJob(getPrintManager(getActivity()),
"testGetTwoPrintJobStates-block"));
assertEquals(job2.getId(), job2.getInfo().getId());
assertEquals(job2.getId(), getPrintJob(getPrintManager(getActivity()),
"testGetTwoPrintJobStates-complete").getId());
assertEquals(job2, getPrintJob(getPrintManager(getActivity()),
"testGetTwoPrintJobStates-complete"));
// First print job should still be there
PrintJob job1again = getPrintJob(getPrintManager(getActivity()),
"testGetTwoPrintJobStates-block");
assertTrue(job1again.isBlocked());
waitForPrinterDiscoverySessionDestroyCallbackCalled(2);
}
@Test
public void changedPrintJobInfo() throws Throwable {
PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_COMPLETED);
long beforeStart = System.currentTimeMillis();
print(adapter, "testPrintJobInfo");
waitForWriteAdapterCallback(1);
long afterStart = System.currentTimeMillis();
PrintJob job = getPrintJob(getPrintManager(getActivity()), "testPrintJobInfo");
// Set some non default options
openPrintOptions();
changeCopies(2);
changeColor("Color");
// Leave duplex as default to test that defaults are retained
changeMediaSize(
PrintAttributes.MediaSize.ISO_A3.getLabel(getActivity().getPackageManager()));
changeOrientation("Landscape");
// Print and wait until it is completed
clickPrintButton();
waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
eventually(job::isCompleted);
// Make sure all options were applied
assertEquals(TEST_PRINTER, job.getInfo().getPrinterId().getLocalId());
assertEquals(2, job.getInfo().getCopies());
assertEquals(PrintAttributes.COLOR_MODE_COLOR,
job.getInfo().getAttributes().getColorMode());
assertEquals(PrintAttributes.DUPLEX_MODE_NONE,
job.getInfo().getAttributes().getDuplexMode());
assertEquals(PrintAttributes.MediaSize.ISO_A3.asLandscape(),
job.getInfo().getAttributes().getMediaSize());
assertEquals(TWO_HUNDRED_DPI, job.getInfo().getAttributes().getResolution());
// Check creation time with 5 sec jitter allowance
assertTrue(beforeStart - 5000 <= job.getInfo().getCreationTime());
assertTrue(job.getInfo().getCreationTime() <= afterStart + 5000);
}
}