blob: 9b277e9ef818eaabdbcea3b7c9482cbc6866d540 [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 android.os.ParcelFileDescriptor;
import android.print.PageRange;
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.PrintDocumentAdapter.LayoutResultCallback;
import android.print.PrintDocumentAdapter.WriteResultCallback;
import android.print.PrintDocumentInfo;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.print.cts.services.FirstPrintService;
import android.print.cts.services.PrintServiceCallbacks;
import android.print.cts.services.PrinterDiscoverySessionCallbacks;
import android.print.cts.services.SecondPrintService;
import android.print.cts.services.StubbablePrinterDiscoverySession;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;
import android.util.Log;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeoutException;
import static android.print.cts.Utils.runOnMainThread;
/**
* This test verifies changes to the printer capabilities are applied correctly.
*/
@RunWith(Parameterized.class)
public class PrinterCapabilitiesChangeTest extends BasePrintTest {
private static final String LOG_TAG = "PrinterCapChangeTest";
private static final String PRINTER_NAME = "Test printer";
private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
private static final Resolution RESOLUTION_300 =
new Resolution("300", "300", 300, 300);
private boolean mAvailBefore;
private MediaSize mMsBefore;
private boolean mAvailAfter;
private MediaSize mMsAfter;
private final StubbablePrinterDiscoverySession[] mSession = new StubbablePrinterDiscoverySession[1];
private final PrinterId[] mPrinterId = new PrinterId[1];
private final PrintAttributes[] mLayoutAttributes = new PrintAttributes[1];
private final PrintAttributes[] mWriteAttributes = new PrintAttributes[1];
private PrintDocumentAdapter mAdapter;
private static boolean sHasDefaultPrinterBeenSet;
/**
* Generate a new list of printers containing a singer printer with the given media size and
* status. The other capabilities are default values.
*
* @param printerId The id of the printer
* @param mediaSize The media size to use
* @param status The status of th printer
*
* @return The list of printers
*/
private List<PrinterInfo> generatePrinters(PrinterId printerId, MediaSize mediaSize,
int status) {
List<PrinterInfo> printers = new ArrayList<>(1);
PrinterCapabilitiesInfo cap;
if (mediaSize != null) {
PrinterCapabilitiesInfo.Builder builder = new PrinterCapabilitiesInfo.Builder(
printerId);
builder.setMinMargins(DEFAULT_MARGINS)
.setColorModes(PrintAttributes.COLOR_MODE_COLOR,
PrintAttributes.COLOR_MODE_COLOR)
.setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
PrintAttributes.DUPLEX_MODE_NONE)
.addMediaSize(mediaSize, true)
.addResolution(RESOLUTION_300, true);
cap = builder.build();
} else {
cap = null;
}
printers.add(new PrinterInfo.Builder(printerId, PRINTER_NAME, status).setCapabilities(cap)
.build());
return printers;
}
/**
* Wait until the print activity requested an update with print attributes matching the media
* size.
*
* @param printAttributes The print attributes container
* @param mediaSize The media size to match
*
* @throws Exception If anything unexpected happened, e.g. the attributes did not change.
*/
private void waitForMediaSizeChange(PrintAttributes[] printAttributes, MediaSize mediaSize)
throws Exception {
synchronized (PrinterCapabilitiesChangeTest.this) {
long endTime = System.currentTimeMillis() + OPERATION_TIMEOUT_MILLIS;
while (printAttributes[0] == null ||
!printAttributes[0].getMediaSize().equals(mediaSize)) {
wait(Math.max(0, endTime - System.currentTimeMillis()));
if (endTime < System.currentTimeMillis()) {
throw new TimeoutException(
"Print attributes did not change to " + mediaSize + " in " +
OPERATION_TIMEOUT_MILLIS + " ms. Current attributes"
+ printAttributes[0]);
}
}
}
}
/**
* Change the media size of the capabilities of the printer
*
* @param session The mSession used in the test
* @param printerId The printer to change
* @param mediaSize The new mediaSize to apply
* @param isAvailable If the printer should be available or not
*/
private void changeCapabilities(final StubbablePrinterDiscoverySession session,
final PrinterId printerId, final MediaSize mediaSize, final boolean isAvailable)
throws Throwable {
runOnMainThread(
() -> session.addPrinters(generatePrinters(printerId, mediaSize, isAvailable ?
PrinterInfo.STATUS_IDLE :
PrinterInfo.STATUS_UNAVAILABLE)));
}
/**
* Wait until the message is shown that indicates that a printer is unavilable.
*
* @throws Exception If anything was unexpected.
*/
private void waitForPrinterUnavailable() throws Exception {
final String PRINTER_UNAVAILABLE_MSG =
getPrintSpoolerString("print_error_printer_unavailable");
UiObject message = getUiDevice().findObject(new UiSelector().resourceId(
"com.android.printspooler:id/message"));
if (!message.getText().equals(PRINTER_UNAVAILABLE_MSG)) {
throw new Exception("Wrong message: " + message.getText() + " instead of " +
PRINTER_UNAVAILABLE_MSG);
}
}
@Before
public void setUpPrinting() throws Exception {
// Create the mSession[0] callbacks that we will be checking.
final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
createMockPrinterDiscoverySessionCallbacks(invocation -> {
mSession[0] = ((PrinterDiscoverySessionCallbacks) invocation.getMock())
.getSession();
mPrinterId[0] = mSession[0].getService().generatePrinterId(PRINTER_NAME);
mSession[0].addPrinters(generatePrinters(mPrinterId[0], MediaSize.NA_LETTER,
PrinterInfo.STATUS_IDLE));
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(createMockPrintServiceCallbacks(null, null, null));
mAdapter = createMockPrintDocumentAdapter(
invocation -> {
LayoutResultCallback callback = (LayoutResultCallback) invocation
.getArguments()[3];
PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(1)
.build();
synchronized (PrinterCapabilitiesChangeTest.this) {
mLayoutAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
PrinterCapabilitiesChangeTest.this.notify();
}
callback.onLayoutFinished(info, true);
return null;
}, invocation -> {
Object[] args = invocation.getArguments();
PageRange[] pages = (PageRange[]) args[0];
ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
WriteResultCallback callback = (WriteResultCallback) args[3];
writeBlankPages(mLayoutAttributes[0], fd, pages[0].getStart(),
pages[0].getEnd());
fd.close();
synchronized (PrinterCapabilitiesChangeTest.this) {
mWriteAttributes[0] = mLayoutAttributes[0];
PrinterCapabilitiesChangeTest.this.notify();
}
callback.onWriteFinished(pages);
onWriteCalled();
return null;
}, null);
if (!sHasDefaultPrinterBeenSet) {
makeDefaultPrinter(mAdapter, PRINTER_NAME);
sHasDefaultPrinterBeenSet = true;
}
resetCounters();
}
@Test
public void changeCapabilities() throws Throwable {
Log.i(LOG_TAG, "Test case: " + mAvailBefore + ", " + mMsBefore + " -> " + mAvailAfter + ", "
+ mMsAfter);
// Start printing.
print(mAdapter);
waitForWriteAdapterCallback(1);
changeCapabilities(mSession[0], mPrinterId[0], mMsBefore, mAvailBefore);
if (mAvailBefore && mMsBefore != null) {
waitForMediaSizeChange(mLayoutAttributes, mMsBefore);
waitForMediaSizeChange(mWriteAttributes, mMsBefore);
} else {
waitForPrinterUnavailable();
}
changeCapabilities(mSession[0], mPrinterId[0], mMsAfter, mAvailAfter);
if (mAvailAfter && mMsAfter != null) {
waitForMediaSizeChange(mLayoutAttributes, mMsAfter);
waitForMediaSizeChange(mWriteAttributes, mMsAfter);
} else {
waitForPrinterUnavailable();
}
// Reset printer to default in case discovery mSession is reused
changeCapabilities(mSession[0], mPrinterId[0], MediaSize.NA_LETTER, true);
waitForMediaSizeChange(mLayoutAttributes, MediaSize.NA_LETTER);
waitForMediaSizeChange(mWriteAttributes, MediaSize.NA_LETTER);
getUiDevice().pressBack();
waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
}
@Parameterized.Parameters
public static Collection<Object[]> getParameters() {
ArrayList<Object[]> parameters = new ArrayList<>();
parameters.add(new Object[]{false, null, false, null});
parameters.add(new Object[]{false, null, false, MediaSize.ISO_A0});
parameters.add(new Object[]{false, null, false, MediaSize.ISO_B0});
parameters.add(new Object[]{false, null, true, null});
parameters.add(new Object[]{false, null, true, MediaSize.ISO_A0});
parameters.add(new Object[]{false, null, true, MediaSize.ISO_B0});
parameters.add(new Object[]{false, MediaSize.ISO_A0, false, null});
parameters.add(new Object[]{false, MediaSize.ISO_A0, false, MediaSize.ISO_A0});
parameters.add(new Object[]{false, MediaSize.ISO_A0, false, MediaSize.ISO_B0});
parameters.add(new Object[]{false, MediaSize.ISO_A0, true, null});
parameters.add(new Object[]{false, MediaSize.ISO_A0, true, MediaSize.ISO_A0});
parameters.add(new Object[]{false, MediaSize.ISO_A0, true, MediaSize.ISO_B0});
parameters.add(new Object[]{true, null, false, null});
parameters.add(new Object[]{true, null, false, MediaSize.ISO_B0});
parameters.add(new Object[]{true, null, true, null});
parameters.add(new Object[]{true, null, true, MediaSize.ISO_B0});
parameters.add(new Object[]{true, MediaSize.ISO_A0, false, null});
parameters.add(new Object[]{true, MediaSize.ISO_A0, false, MediaSize.ISO_A0});
parameters.add(new Object[]{true, MediaSize.ISO_A0, false, MediaSize.ISO_B0});
parameters.add(new Object[]{true, MediaSize.ISO_A0, true, null});
parameters.add(new Object[]{true, MediaSize.ISO_A0, true, MediaSize.ISO_A0});
parameters.add(new Object[]{true, MediaSize.ISO_A0, true, MediaSize.ISO_B0});
return parameters;
}
public PrinterCapabilitiesChangeTest(boolean availBefore, MediaSize msBefore,
boolean availAfter, MediaSize msAfter) {
mAvailBefore = availBefore;
mMsBefore = msBefore;
mAvailAfter = availAfter;
mMsAfter = msAfter;
}
}