• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2016 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package android.print.cts;
18  
19  import static android.print.test.Utils.assertException;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertTrue;
23  
24  import android.os.ParcelFileDescriptor;
25  import android.print.PageRange;
26  import android.print.PrintAttributes;
27  import android.print.PrintAttributes.Margins;
28  import android.print.PrintAttributes.MediaSize;
29  import android.print.PrintAttributes.Resolution;
30  import android.print.PrintDocumentAdapter;
31  import android.print.PrintDocumentAdapter.LayoutResultCallback;
32  import android.print.PrintDocumentAdapter.WriteResultCallback;
33  import android.print.PrintDocumentInfo;
34  import android.print.PrinterCapabilitiesInfo;
35  import android.print.PrinterId;
36  import android.print.PrinterInfo;
37  import android.print.test.BasePrintTest;
38  import android.print.test.services.FirstPrintService;
39  import android.print.test.services.PrintServiceCallbacks;
40  import android.print.test.services.PrinterDiscoverySessionCallbacks;
41  import android.print.test.services.SecondPrintService;
42  import android.print.test.services.StubbablePrinterDiscoverySession;
43  
44  import androidx.test.runner.AndroidJUnit4;
45  
46  import org.junit.Test;
47  import org.junit.runner.RunWith;
48  
49  import java.util.ArrayList;
50  import java.util.function.Consumer;
51  import java.util.function.Function;
52  
53  /**
54   * This test verifies changes to the printer capabilities are applied correctly.
55   */
56  @RunWith(AndroidJUnit4.class)
57  public class PrinterCapabilitiesTest extends BasePrintTest {
58      private static final String PRINTER_NAME = "Test printer";
59  
60      private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
61      private static final PrintAttributes.Resolution RESOLUTION_300 =
62              new PrintAttributes.Resolution("300", "300", 300, 300);
63      private static final PrintAttributes.Resolution RESOLUTION_600 =
64              new PrintAttributes.Resolution("600", "600", 600, 600);
65      private static boolean sDefaultPrinterBeenSet;
66  
67      /**
68       * That that you cannot create illegal PrinterCapabilityInfos.
69       *
70       * @throws Exception If anything is unexpected
71       */
72      @Test
illegalPrinterCapabilityInfos()73      public void illegalPrinterCapabilityInfos() throws Exception {
74          final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
75                  createMockPrinterDiscoverySessionCallbacks(invocation -> {
76                      StubbablePrinterDiscoverySession session =
77                              ((PrinterDiscoverySessionCallbacks)
78                                      invocation.getMock()).getSession();
79  
80                      PrinterId printerId = session.getService().generatePrinterId(PRINTER_NAME);
81  
82                      // printerId need to be set
83                      assertException(() -> new PrinterCapabilitiesInfo.Builder(null),
84                              IllegalArgumentException.class);
85  
86                      // All capability fields (beside duplex) need to be initialized:
87                      // Test no color
88                      assertException(() ->
89                                      (new PrinterCapabilitiesInfo.Builder(printerId))
90                                              .setMinMargins(DEFAULT_MARGINS)
91                                              .addMediaSize(MediaSize.ISO_A4, true)
92                                              .addResolution(RESOLUTION_300, true).build(),
93                              IllegalStateException.class);
94                      // Test bad colors
95                      assertException(() ->
96                                      (new PrinterCapabilitiesInfo.Builder(printerId))
97                                              .setColorModes(0xffff,
98                                                      PrintAttributes.COLOR_MODE_MONOCHROME),
99                              IllegalArgumentException.class);
100                      // Test bad duplex mode
101                      assertException(() ->
102                                      (new PrinterCapabilitiesInfo.Builder(printerId))
103                                              .setDuplexModes(0xffff,
104                                                      PrintAttributes.DUPLEX_MODE_NONE),
105                              IllegalArgumentException.class);
106                      // Test no mediasize
107                      assertException(() ->
108                                      (new PrinterCapabilitiesInfo.Builder(printerId))
109                                              .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
110                                                      PrintAttributes.COLOR_MODE_COLOR)
111                                              .setMinMargins(DEFAULT_MARGINS)
112                                              .addResolution(RESOLUTION_300, true).build(),
113                              IllegalStateException.class);
114                      // Test no default mediasize
115                      assertException(() ->
116                                      (new PrinterCapabilitiesInfo.Builder(printerId))
117                                              .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
118                                                      PrintAttributes.COLOR_MODE_COLOR)
119                                              .setMinMargins(DEFAULT_MARGINS)
120                                              .addMediaSize(MediaSize.ISO_A4, false)
121                                              .addResolution(RESOLUTION_300, true).build(),
122                              IllegalStateException.class);
123                      // Test two default mediasizes
124                      assertException(() ->
125                                      (new PrinterCapabilitiesInfo.Builder(printerId))
126                                              .addMediaSize(MediaSize.ISO_A4, true)
127                                              .addMediaSize(MediaSize.ISO_A5, true),
128                              IllegalArgumentException.class);
129                      // Test no resolution
130                      assertException(() ->
131                                      (new PrinterCapabilitiesInfo.Builder(printerId))
132                                              .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
133                                                      PrintAttributes.COLOR_MODE_COLOR)
134                                              .setMinMargins(DEFAULT_MARGINS)
135                                              .addMediaSize(MediaSize.ISO_A4, true).build(),
136                              IllegalStateException.class);
137                      // Test no default resolution
138                      assertException(() ->
139                                      (new PrinterCapabilitiesInfo.Builder(printerId))
140                                              .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
141                                                      PrintAttributes.COLOR_MODE_COLOR)
142                                              .setMinMargins(DEFAULT_MARGINS)
143                                              .addMediaSize(MediaSize.ISO_A4, true)
144                                              .addResolution(RESOLUTION_300, false).build(),
145                              IllegalStateException.class);
146                      // Test two default resolutions
147                      assertException(() ->
148                                      (new PrinterCapabilitiesInfo.Builder(printerId))
149                                              .addResolution(RESOLUTION_300, true)
150                                              .addResolution(RESOLUTION_600, true),
151                              IllegalArgumentException.class);
152  
153                      onPrinterDiscoverySessionCreateCalled();
154                      return null;
155                  }, null, null, null, null, null, invocation -> {
156                      onPrinterDiscoverySessionDestroyCalled();
157                      return null;
158                  });
159  
160          // Create the service callbacks for the first print service.
161          PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
162                  invocation -> firstSessionCallbacks, null, null);
163  
164          // Configure the print services.
165          FirstPrintService.setCallbacks(firstServiceCallbacks);
166          SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
167  
168          PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(null, null, null);
169  
170          // Start printing.
171          print(adapter);
172  
173          waitForPrinterDiscoverySessionCreateCallbackCalled();
174  
175          getActivity().finish();
176  
177          waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
178      }
179  
180      /**
181       * That that you can use all sane legal PrinterCapabilityInfos.
182       *
183       * @throws Exception If anything is unexpected
184       */
185      @Test
sanePrinterCapabilityInfos()186      public void sanePrinterCapabilityInfos() throws Exception {
187          final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
188                  createMockPrinterDiscoverySessionCallbacks(invocation -> {
189                      StubbablePrinterDiscoverySession session =
190                              ((PrinterDiscoverySessionCallbacks)
191                                      invocation.getMock()).getSession();
192  
193                      MediaSize[] mediaSizes = {MediaSize.ISO_A0, MediaSize.ISO_A0,
194                              MediaSize.ISO_A1};
195                      Resolution[] resolutions = {RESOLUTION_300, RESOLUTION_300,
196                              RESOLUTION_600};
197                      int[] colorModes = {PrintAttributes.COLOR_MODE_MONOCHROME,
198                              PrintAttributes.COLOR_MODE_COLOR};
199                      int[] duplexModes = {PrintAttributes.DUPLEX_MODE_NONE,
200                              PrintAttributes.DUPLEX_MODE_LONG_EDGE,
201                              PrintAttributes.DUPLEX_MODE_SHORT_EDGE};
202  
203                      ArrayList<PrinterInfo> printers = new ArrayList<>();
204                      for (int mediaSizeIndex = 1; mediaSizeIndex < mediaSizes.length;
205                           mediaSizeIndex++) {
206                          for (int resolutionIndex = 1; resolutionIndex < mediaSizes.length;
207                               resolutionIndex++) {
208                              for (int colorIndex = 1; colorIndex < colorModes.length;
209                                   colorIndex++) {
210                                  for (int duplexIndex = 1; duplexIndex < duplexModes.length;
211                                       duplexIndex++) {
212                                      PrinterId printerId = session.getService()
213                                              .generatePrinterId(Integer.valueOf(printers.size())
214                                                      .toString());
215  
216                                      // Setup capabilities
217                                      PrinterCapabilitiesInfo.Builder b =
218                                              new PrinterCapabilitiesInfo.Builder(printerId);
219  
220                                      for (int i = 0; i < mediaSizeIndex; i++) {
221                                          b.addMediaSize(mediaSizes[i], i == mediaSizeIndex - 1);
222                                      }
223  
224                                      for (int i = 0; i < resolutionIndex; i++) {
225                                          b.addResolution(resolutions[i],
226                                                  i == resolutionIndex - 1);
227                                      }
228  
229                                      int allColors = 0;
230                                      for (int i = 0; i < colorIndex; i++) {
231                                          allColors |= colorModes[i];
232                                      }
233                                      b.setColorModes(allColors, colorModes[colorIndex - 1]);
234  
235                                      int allDuplexModes = 0;
236                                      for (int i = 0; i < duplexIndex; i++) {
237                                          allDuplexModes |= duplexModes[i];
238                                      }
239                                      b.setDuplexModes(allDuplexModes,
240                                              duplexModes[duplexIndex - 1]);
241  
242                                      b.setMinMargins(DEFAULT_MARGINS);
243  
244                                      // Create printer
245                                      PrinterInfo printer = (new PrinterInfo.Builder(printerId,
246                                              Integer.valueOf(printers.size()).toString(),
247                                              PrinterInfo.STATUS_IDLE)).setCapabilities(b.build())
248                                              .build();
249  
250                                      // Verify capabilities
251                                      PrinterCapabilitiesInfo cap = printer.getCapabilities();
252  
253                                      assertEquals(mediaSizeIndex, cap.getMediaSizes().size());
254                                      assertEquals(mediaSizes[mediaSizeIndex - 1],
255                                              cap.getDefaults().getMediaSize());
256                                      for (int i = 0; i < mediaSizeIndex; i++) {
257                                          assertTrue(cap.getMediaSizes().contains(mediaSizes[i]));
258                                      }
259  
260                                      assertEquals(resolutionIndex, cap.getResolutions().size());
261                                      assertEquals(resolutions[resolutionIndex - 1],
262                                              cap.getDefaults().getResolution());
263                                      for (int i = 0; i < resolutionIndex; i++) {
264                                          assertTrue(cap.getResolutions().contains(resolutions[i]));
265                                      }
266  
267                                      assertEquals(allColors, cap.getColorModes());
268                                      assertEquals(colorModes[colorIndex - 1],
269                                              cap.getDefaults().getColorMode());
270  
271                                      assertEquals(allDuplexModes, cap.getDuplexModes());
272                                      assertEquals(duplexModes[duplexIndex - 1],
273                                              cap.getDefaults().getDuplexMode());
274  
275                                      assertEquals(DEFAULT_MARGINS, cap.getMinMargins());
276  
277                                      // Add printer
278                                      printers.add(printer);
279                                  }
280                              }
281                          }
282                      }
283  
284                      session.addPrinters(printers);
285  
286                      onPrinterDiscoverySessionCreateCalled();
287                      return null;
288                  }, null, null, null, null, null, invocation -> {
289                      onPrinterDiscoverySessionDestroyCalled();
290                      return null;
291                  });
292  
293          // Create the service callbacks for the first print service.
294          PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
295                  invocation -> firstSessionCallbacks, null, null);
296  
297          // Configure the print services.
298          FirstPrintService.setCallbacks(firstServiceCallbacks);
299          SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
300  
301          PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(null, null, null);
302  
303          // Start printing.
304          print(adapter);
305  
306          waitForPrinterDiscoverySessionCreateCallbackCalled();
307  
308          mPrintHelper.cancelPrinting();
309  
310          waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
311      }
312  
313      /**
314       * Base test that performs a print operation with a give PrinterCapabilityInfo and run a test
315       * function before finishing.
316       *
317       * @throws Exception
318       */
testPrinterCapabilityInfo(final Function<PrinterId, PrinterCapabilitiesInfo> capBuilder, Consumer<PrintAttributes> test)319      private void testPrinterCapabilityInfo(final Function<PrinterId, PrinterCapabilitiesInfo>
320              capBuilder, Consumer<PrintAttributes> test) throws Exception {
321          final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
322                  createMockPrinterDiscoverySessionCallbacks(invocation -> {
323                      StubbablePrinterDiscoverySession session =
324                              ((PrinterDiscoverySessionCallbacks)
325                                      invocation.getMock()).getSession();
326  
327                      PrinterId printerId = session.getService()
328                              .generatePrinterId(PRINTER_NAME);
329  
330                      ArrayList<PrinterInfo> printers = new ArrayList<>();
331                      printers.add((new PrinterInfo.Builder(printerId, PRINTER_NAME,
332                              PrinterInfo.STATUS_IDLE))
333                              .setCapabilities(capBuilder.apply(printerId)).build());
334  
335                      session.addPrinters(printers);
336  
337                      onPrinterDiscoverySessionCreateCalled();
338                      return null;
339                  }, null, null, null, null, null, invocation -> {
340                      onPrinterDiscoverySessionDestroyCalled();
341                      return null;
342                  });
343  
344          // Create the service callbacks for the first print service.
345          PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
346                  invocation -> firstSessionCallbacks, null, null);
347  
348          // Configure the print services.
349          FirstPrintService.setCallbacks(firstServiceCallbacks);
350          SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
351  
352          final PrintAttributes[] layoutAttributes = new PrintAttributes[1];
353  
354          PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
355                  invocation -> {
356                      LayoutResultCallback callback = (LayoutResultCallback) invocation
357                              .getArguments()[3];
358                      PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
359                              .setPageCount(1)
360                              .build();
361                      layoutAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
362  
363                      callback.onLayoutFinished(info, true);
364                      return null;
365                  },
366                  invocation -> {
367                      Object[] args = invocation.getArguments();
368                      PageRange[] pages = (PageRange[]) args[0];
369                      ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
370                      WriteResultCallback callback = (WriteResultCallback) args[3];
371  
372                      writeBlankPages(layoutAttributes[0], fd, pages[0].getStart(),
373                              pages[0].getEnd());
374                      fd.close();
375  
376                      callback.onWriteFinished(pages);
377                      return null;
378                  }, null);
379  
380          // Start printing.
381          print(adapter);
382  
383          // make sure that options does not crash
384          openPrintOptions();
385  
386          if (!sDefaultPrinterBeenSet) {
387              // Select printer under test
388              selectPrinter(PRINTER_NAME);
389          }
390  
391          mPrintHelper.submitPrintJob();
392  
393          if (!sDefaultPrinterBeenSet) {
394              answerPrintServicesWarning(true);
395              sDefaultPrinterBeenSet = true;
396          }
397  
398          test.accept(layoutAttributes[0]);
399  
400          waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
401      }
402  
403      /**
404       * That that you use a default color that is not in the allowed colors. This is allowed because
405       * of historical reasons.
406       *
407       * @throws Exception If anything is unexpected
408       */
409      @Test
invalidDefaultColor()410      public void invalidDefaultColor() throws Exception {
411          testPrinterCapabilityInfo(
412                  (printerId) -> (new PrinterCapabilitiesInfo.Builder(printerId))
413                          .addMediaSize(MediaSize.ISO_A4, true)
414                          .addResolution(RESOLUTION_300, true)
415                          .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
416                                  PrintAttributes.COLOR_MODE_COLOR).build(),
417                  (layoutAttributes) -> assertEquals(layoutAttributes.getColorMode(),
418                          PrintAttributes.COLOR_MODE_MONOCHROME));
419      }
420  
421      /**
422       * That that you use a default duplex mode that is not in the allowed duplex modes. This is
423       * allowed because of historical reasons.
424       *
425       * @throws Exception If anything is unexpected
426       */
427      @Test
invalidDefaultDuplexMode()428      public void invalidDefaultDuplexMode() throws Exception {
429          testPrinterCapabilityInfo(
430                  (printerId) -> (new PrinterCapabilitiesInfo.Builder(printerId))
431                          .addMediaSize(MediaSize.ISO_A4, true)
432                          .addResolution(RESOLUTION_300, true)
433                          .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
434                                  PrintAttributes.COLOR_MODE_MONOCHROME)
435                          .setDuplexModes(PrintAttributes.DUPLEX_MODE_LONG_EDGE
436                                  | PrintAttributes.DUPLEX_MODE_NONE,
437                                  PrintAttributes.DUPLEX_MODE_SHORT_EDGE).build(),
438                  (layoutAttributes) -> assertTrue(layoutAttributes.getDuplexMode() ==
439                          PrintAttributes.DUPLEX_MODE_LONG_EDGE || layoutAttributes.getDuplexMode() ==
440                          PrintAttributes.DUPLEX_MODE_NONE));
441      }
442  }
443