blob: 6e67dee478c18513c1cc964a83f0462660bad635 [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.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
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.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;
import android.text.TextUtils;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
/**
* Tests all allowed types of printerInfo
*/
@RunWith(AndroidJUnit4.class)
public class PrinterInfoTest extends BasePrintTest {
private static final String NAMED_PRINTERS_NAME_PREFIX = "Printer ";
/** The printer discovery session used in this test */
private static StubbablePrinterDiscoverySession sDiscoverySession;
private boolean isValidStatus(int status) {
return status == PrinterInfo.STATUS_IDLE
|| status == PrinterInfo.STATUS_BUSY
|| status == PrinterInfo.STATUS_UNAVAILABLE;
}
/**
* Create a mock {@link PrinterDiscoverySessionCallbacks} that discovers a printers with all
* possible combinations of interesting printers.
*
* @return The mock session callbacks
*/
private PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
return createMockPrinterDiscoverySessionCallbacks(invocation -> {
// Get the session.
sDiscoverySession = ((PrinterDiscoverySessionCallbacks) invocation.getMock())
.getSession();
if (sDiscoverySession.getPrinters().isEmpty()) {
final int INVALID_RES_ID = 0xffffffff;
final PrinterInfo.Builder badPrinter = new PrinterInfo.Builder(
sDiscoverySession.getService().generatePrinterId("bad printer"),
"badPrinter", PrinterInfo.STATUS_UNAVAILABLE);
String[] localPrinterIds = {
"Printer", null
};
String[] names = {
NAMED_PRINTERS_NAME_PREFIX, "", null
};
int[] statusList = {
PrinterInfo.STATUS_IDLE, PrinterInfo.STATUS_BUSY,
PrinterInfo.STATUS_UNAVAILABLE, 0, 42
};
int[] iconResourceIds = {
R.drawable.red_printer, 0, INVALID_RES_ID, -1
};
boolean[] hasCustomPrinterIcons = {
true, false
};
String[] descriptions = {
"Description", "", null
};
PendingIntent[] infoIntents = {
PendingIntent.getActivity(getActivity(), 0,
new Intent(getActivity(), Activity.class),
PendingIntent.FLAG_IMMUTABLE),
null
};
PrinterCapabilitiesInfo[] capabilityList = {
// The printerId not used in PrinterCapabilitiesInfo
new PrinterCapabilitiesInfo.Builder(sDiscoverySession.getService()
.generatePrinterId("unused"))
.setMinMargins(new Margins(200, 200, 200, 200))
.addMediaSize(MediaSize.ISO_A4, true)
.addResolution(
new Resolution("300x300", "300x300", 300, 300),
true)
.setColorModes(PrintAttributes.COLOR_MODE_COLOR,
PrintAttributes.COLOR_MODE_COLOR)
.build(),
null
};
List<PrinterInfo> printers = new ArrayList<>();
for (String localPrinterId : localPrinterIds) {
for (String name : names) {
for (int status : statusList) {
for (int iconResourceId : iconResourceIds) {
for (boolean hasCustomPrinterIcon : hasCustomPrinterIcons) {
for (String description : descriptions) {
for (PendingIntent infoIntent : infoIntents) {
for (PrinterCapabilitiesInfo capabilities
: capabilityList) {
// printerId
RuntimeException e = null;
PrinterId printerId = null;
try {
if (localPrinterId == null) {
printerId = sDiscoverySession
.getService()
.generatePrinterId(
localPrinterId);
} else {
printerId = sDiscoverySession
.getService()
.generatePrinterId(
localPrinterId
+ printers
.size());
}
} catch (RuntimeException ex) {
e = ex;
}
// Expect exception if localId is null
if (localPrinterId == null) {
if (e == null) {
throw new IllegalStateException();
}
} else if (e != null) {
throw e;
}
// Constructor
PrinterInfo.Builder b = null;
e = null;
try {
b = new PrinterInfo.Builder(
printerId, name, status);
} catch (RuntimeException ex) {
e = ex;
}
// Expect exception if any of the parameters was
// bad
if (printerId == null
|| TextUtils.isEmpty(name)
|| !isValidStatus(status)) {
if (e == null) {
throw new IllegalStateException();
} else {
b = badPrinter;
}
} else if (e != null) {
throw e;
}
// IconResourceId
e = null;
try {
b.setIconResourceId(iconResourceId);
} catch (RuntimeException ex) {
e = ex;
}
// Expect exception if iconResourceId was bad
// We do allow invalid Ids as the printerInfo
// might be created after the package of the
// printer is already gone if the printer is a
// historical printer.
if (iconResourceId < 0) {
if (e == null) {
throw new IllegalStateException();
} else {
b = badPrinter;
}
} else if (e != null) {
throw e;
}
// Status
e = null;
try {
b.setStatus(status);
} catch (RuntimeException ex) {
e = ex;
}
// Expect exception is status is not valid
if (!isValidStatus(status)) {
if (e == null) {
throw new IllegalStateException();
} else {
b = badPrinter;
}
} else if (e != null) {
throw e;
}
// Name
e = null;
try {
b.setName(name);
} catch (RuntimeException ex) {
e = ex;
}
// Expect exception if name is empty
if (TextUtils.isEmpty(name)) {
if (e == null) {
throw new IllegalStateException();
} else {
b = badPrinter;
}
} else if (e != null) {
throw e;
}
// hasCustomPrinterIcon
b.setHasCustomPrinterIcon(hasCustomPrinterIcon);
// Description
b.setDescription(description);
// InfoIntent
b.setInfoIntent(infoIntent);
// Capabilities
b.setCapabilities(capabilities);
PrinterInfo printer = b.build();
// Don't create bad printers
if (b == badPrinter) {
continue;
}
// Verify get* methods
if (printer.getId() != printerId
|| printer.getName() != name
|| printer.getStatus() != status
|| printer
.getDescription() != description
|| printer.getCapabilities()
!= capabilities) {
throw new IllegalStateException();
}
printers.add(printer);
}
}
}
}
}
}
}
}
sDiscoverySession.addPrinters(printers);
}
return null;
}, null, null, invocation -> null, invocation -> null, null, invocation -> {
// Take a note onDestroy was called.
onPrinterDiscoverySessionDestroyCalled();
return null;
});
}
/**
* Create mock service callback for a session.
*
* @param sessionCallbacks The callbacks of the session
*/
private PrintServiceCallbacks createFirstMockPrinterServiceCallbacks(
final PrinterDiscoverySessionCallbacks sessionCallbacks) {
return createMockPrintServiceCallbacks(
invocation -> sessionCallbacks,
null, null);
}
/**
* Test that all printInfos possible can be used and that invalid printInfos throw exceptions.
*
* @throws Exception If anything is unexpected.
*/
@Test
public void printerInfos() throws Exception {
// 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);
// 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));
// 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);
// Open destination spinner
UiObject destinationSpinner = getUiDevice().findObject(new UiSelector().resourceId(
"com.android.printspooler:id/destination_spinner"));
destinationSpinner.click();
// Wait until spinner is opened
getUiDevice().waitForIdle();
// Exit print spooler
getUiDevice().pressBack();
getUiDevice().pressBack();
getUiDevice().pressBack();
}
}