2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package android.print;
19 import android.annotation.NonNull;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.os.CancellationSignal;
24 import android.os.Handler;
25 import android.os.Looper;
26 import android.os.ParcelFileDescriptor;
27 import android.os.Process;
28 import android.os.ServiceManager;
29 import android.os.UserHandle;
30 import android.print.PrintAttributes.Margins;
31 import android.print.PrintAttributes.MediaSize;
32 import android.print.PrintAttributes.Resolution;
33 import android.printservice.PrintServiceInfo;
35 import android.print.mockservice.MockPrintService;
36 import android.print.mockservice.PrintServiceCallbacks;
37 import android.print.mockservice.PrinterDiscoverySessionCallbacks;
38 import android.print.mockservice.StubbablePrinterDiscoverySession;
40 import org.mockito.invocation.InvocationOnMock;
41 import org.mockito.stubbing.Answer;
43 import java.util.ArrayList;
44 import java.util.List;
47 * tests feeding all possible parameters to the IPrintManager Binder.
49 public class IPrintManagerParametersTest extends BasePrintTest {
51 private final int BAD_APP_ID = 0xffffffff;
53 private final int mAppId;
54 private final int mUserId;
55 private final PrintJobId mBadPrintJobId;
57 private PrintJob mGoodPrintJob;
58 private PrinterId mBadPrinterId;
59 private PrinterId mGoodPrinterId;
60 private ComponentName mGoodComponentName;
61 private ComponentName mBadComponentName;
63 private IPrintManager mIPrintManager;
66 * Create a new IPrintManagerParametersTest and setup basic fields.
68 public IPrintManagerParametersTest() {
71 mAppId = UserHandle.getAppId(Process.myUid());
72 mUserId = UserHandle.myUserId();
73 mBadPrintJobId = new PrintJobId();
74 mBadComponentName = new ComponentName("bad", "bad");
78 * Create a mock PrintDocumentAdapter.
82 private @NonNull PrintDocumentAdapter createMockAdapter() {
83 return new PrintDocumentAdapter() {
85 public void onStart() {
90 public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
91 CancellationSignal cancellationSignal, LayoutResultCallback callback,
96 public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
97 CancellationSignal cancellationSignal, WriteResultCallback callback) {
103 * Create mock print service callbacks.
105 * @return the callbacks
107 private PrintServiceCallbacks createMockCallbacks() {
108 return createMockPrintServiceCallbacks(
109 new Answer<PrinterDiscoverySessionCallbacks>() {
111 public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
112 return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
114 public Void answer(InvocationOnMock invocation) {
116 StubbablePrinterDiscoverySession session =
117 ((PrinterDiscoverySessionCallbacks) invocation
118 .getMock()).getSession();
120 if (session.getPrinters().isEmpty()) {
121 final String PRINTER_NAME = "good printer";
122 List<PrinterInfo> printers = new ArrayList<>();
125 mGoodPrinterId = session.getService()
126 .generatePrinterId(PRINTER_NAME);
128 PrinterCapabilitiesInfo capabilities =
129 new PrinterCapabilitiesInfo.Builder(mGoodPrinterId)
131 new Margins(200, 200, 200, 200))
132 .addMediaSize(MediaSize.ISO_A4, true)
133 .addResolution(new Resolution("300x300",
134 "300x300", 300, 300),
137 PrintAttributes.COLOR_MODE_COLOR,
138 PrintAttributes.COLOR_MODE_COLOR)
141 PrinterInfo printer = new PrinterInfo.Builder(
144 PrinterInfo.STATUS_IDLE)
145 .setCapabilities(capabilities)
147 printers.add(printer);
149 session.addPrinters(printers);
151 onPrinterDiscoverySessionStartCalled();
154 }, null, null, null, null, null, null);
161 * Create a IPrintJobStateChangeListener object.
164 * @throws Exception if the object could not be created.
166 private IPrintJobStateChangeListener createMockIPrintJobStateChangeListener() throws Exception {
167 return new PrintManager.PrintJobStateChangeListenerWrapper(null,
168 new Handler(Looper.getMainLooper()));
172 * Create a IPrintServicesChangeListener object.
175 * @throws Exception if the object could not be created.
177 private IPrintServicesChangeListener createMockIPrintServicesChangeListener() throws Exception {
178 return new PrintManager.PrintServicesChangeListenerWrapper(null,
179 new Handler(Looper.getMainLooper()));
184 * Create a IPrinterDiscoveryObserver object.
187 * @throws Exception if the object could not be created.
189 private IPrinterDiscoveryObserver createMockIPrinterDiscoveryObserver() throws Exception {
190 return new PrinterDiscoverySession.PrinterDiscoveryObserver(null);
193 private void startPrinting() {
194 mGoodPrintJob = print(createMockAdapter(), null);
196 // Wait for PrintActivity to be ready
197 waitForStartAdapterCallbackCalled();
199 // Wait for printer discovery session to be ready
200 waitForPrinterDiscoverySessionStartCallbackCalled();
204 public void setUp() throws Exception {
207 MockPrintService.setCallbacks(createMockCallbacks());
209 mGoodComponentName = getActivity().getComponentName();
211 mIPrintManager = IPrintManager.Stub
212 .asInterface(ServiceManager.getService(Context.PRINT_SERVICE));
214 // Generate dummy printerId which is a valid PrinterId object, but does not correspond to a
216 mBadPrinterId = new PrinterId(mGoodComponentName, "dummy printer");
220 * {@link Runnable} that can throw and {@link Exception}
222 private interface Invokable {
224 * Execute the invokable
228 void run() throws Exception;
232 * Assert that the invokable throws an expectedException
234 * @param invokable The {@link Invokable} to run
235 * @param expectedClass The {@link Exception} that is supposed to be thrown
237 public void assertException(Invokable invokable, Class<? extends Exception> expectedClass)
241 } catch (Exception e) {
242 if (e.getClass().isAssignableFrom(expectedClass)) {
245 throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
246 + e.getClass().getName());
250 throw new AssertionError("No exception thrown");
254 * test IPrintManager.getPrintJobInfo
256 public void testGetPrintJobInfo() throws Exception {
259 assertEquals(mGoodPrintJob.getId(), mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(),
260 mAppId, mUserId).getId());
261 assertEquals(null, mIPrintManager.getPrintJobInfo(mBadPrintJobId, mAppId, mUserId));
262 assertEquals(null, mIPrintManager.getPrintJobInfo(null, mAppId, mUserId));
264 assertException(new Invokable() {
266 public void run() throws Exception {
267 mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
269 }, SecurityException.class);
271 // Cannot test bad user Id as these tests are allowed to call across users
275 * test IPrintManager.getPrintJobInfos
277 public void testGetPrintJobInfos() throws Exception {
280 List<PrintJobInfo> infos = mIPrintManager.getPrintJobInfos(mAppId, mUserId);
282 boolean foundPrintJob = false;
283 for (PrintJobInfo info : infos) {
284 if (info.getId().equals(mGoodPrintJob.getId())) {
285 assertEquals(PrintJobInfo.STATE_CREATED, info.getState());
286 foundPrintJob = true;
289 assertTrue(foundPrintJob);
291 assertException(new Invokable() {
293 public void run() throws Exception {
294 mIPrintManager.getPrintJobInfos(BAD_APP_ID, mUserId);
296 }, SecurityException.class);
298 // Cannot test bad user Id as these tests are allowed to call across users
302 * test IPrintManager.print
304 public void testPrint() throws Exception {
305 final String name = "dummy print job";
307 final IPrintDocumentAdapter adapter = new PrintManager
308 .PrintDocumentAdapterDelegate(getActivity(), createMockAdapter());
312 assertException(new Invokable() {
314 public void run() throws Exception {
315 mIPrintManager.print(null, adapter, null, mGoodComponentName.getPackageName(),
318 }, IllegalArgumentException.class);
320 assertException(new Invokable() {
322 public void run() throws Exception {
323 mIPrintManager.print(name, null, null, mGoodComponentName.getPackageName(),
326 }, NullPointerException.class);
328 assertException(new Invokable() {
330 public void run() throws Exception {
331 mIPrintManager.print(name, adapter, null, null, mAppId, mUserId);
333 }, IllegalArgumentException.class);
335 assertException(new Invokable() {
337 public void run() throws Exception {
338 mIPrintManager.print(name, adapter, null, mBadComponentName.getPackageName(),
341 }, IllegalArgumentException.class);
343 assertException(new Invokable() {
345 public void run() throws Exception {
346 mIPrintManager.print(name, adapter, null, mGoodComponentName.getPackageName(),
347 BAD_APP_ID, mUserId);
349 }, SecurityException.class);
351 // Cannot test bad user Id as these tests are allowed to call across users
355 * test IPrintManager.cancelPrintJob
357 public void testCancelPrintJob() throws Exception {
360 // Invalid print jobs IDs do not produce an exception
361 mIPrintManager.cancelPrintJob(mBadPrintJobId, mAppId, mUserId);
362 mIPrintManager.cancelPrintJob(null, mAppId, mUserId);
364 assertException(new Invokable() {
366 public void run() throws Exception {
367 mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
369 }, SecurityException.class);
371 // Cannot test bad user Id as these tests are allowed to call across users
373 // Must be last as otherwise mGoodPrintJob will not be good anymore
374 mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), mAppId, mUserId);
378 * test IPrintManager.restartPrintJob
380 public void testRestartPrintJob() throws Exception {
383 mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), mAppId, mUserId);
385 // Invalid print jobs IDs do not produce an exception
386 mIPrintManager.restartPrintJob(mBadPrintJobId, mAppId, mUserId);
387 mIPrintManager.restartPrintJob(null, mAppId, mUserId);
389 assertException(new Invokable() {
391 public void run() throws Exception {
392 mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
394 }, SecurityException.class);
396 // Cannot test bad user Id as these tests are allowed to call across users
400 * test IPrintManager.addPrintJobStateChangeListener
402 public void testAddPrintJobStateChangeListener() throws Exception {
403 final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
405 mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
407 assertException(new Invokable() {
409 public void run() throws Exception {
410 mIPrintManager.addPrintJobStateChangeListener(null, mAppId, mUserId);
412 }, NullPointerException.class);
414 assertException(new Invokable() {
416 public void run() throws Exception {
417 mIPrintManager.addPrintJobStateChangeListener(listener, BAD_APP_ID, mUserId);
419 }, SecurityException.class);
421 // Cannot test bad user Id as these tests are allowed to call across users
425 * test IPrintManager.removePrintJobStateChangeListener
427 public void testRemovePrintJobStateChangeListener() throws Exception {
428 final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
430 mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
431 mIPrintManager.removePrintJobStateChangeListener(listener, mUserId);
433 // Removing unknown listeners is a no-op
434 mIPrintManager.removePrintJobStateChangeListener(listener, mUserId);
436 mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
437 assertException(new Invokable() {
439 public void run() throws Exception {
440 mIPrintManager.removePrintJobStateChangeListener(null, mUserId);
442 }, NullPointerException.class);
444 // Cannot test bad user Id as these tests are allowed to call across users
448 * test IPrintManager.addPrintServicesChangeListener
450 public void testAddPrintServicesChangeListener() throws Exception {
451 final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
453 mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
455 assertException(new Invokable() {
457 public void run() throws Exception {
458 mIPrintManager.addPrintServicesChangeListener(null, mUserId);
460 }, NullPointerException.class);
462 // Cannot test bad user Id as these tests are allowed to call across users
466 * test IPrintManager.removePrintServicesChangeListener
468 public void testRemovePrintServicesChangeListener() throws Exception {
469 final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
471 mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
472 mIPrintManager.removePrintServicesChangeListener(listener, mUserId);
474 // Removing unknown listeners is a no-op
475 mIPrintManager.removePrintServicesChangeListener(listener, mUserId);
477 mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
478 assertException(new Invokable() {
480 public void run() throws Exception {
481 mIPrintManager.removePrintServicesChangeListener(null, mUserId);
483 }, NullPointerException.class);
485 // Cannot test bad user Id as these tests are allowed to call across users
489 * test IPrintManager.getPrintServices
491 public void testGetPrintServices() throws Exception {
492 List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
493 PrintManager.ALL_SERVICES, mUserId);
494 assertTrue(printServices.size() >= 2);
496 printServices = mIPrintManager.getPrintServices(0, mUserId);
497 assertEquals(printServices, null);
499 assertException(new Invokable() {
501 public void run() throws Exception {
502 mIPrintManager.getPrintServices(~PrintManager.ALL_SERVICES, mUserId);
504 }, IllegalArgumentException.class);
506 // Cannot test bad user Id as these tests are allowed to call across users
510 * test IPrintManager.setPrintServiceEnabled
512 public void testSetPrintServiceEnabled() throws Exception {
513 final ComponentName printService = mIPrintManager.getPrintServices(
514 PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
516 assertException(new Invokable() {
518 public void run() throws Exception {
519 mIPrintManager.setPrintServiceEnabled(printService, false, mUserId);
521 }, SecurityException.class);
523 assertException(new Invokable() {
525 public void run() throws Exception {
526 mIPrintManager.setPrintServiceEnabled(printService, true, mUserId);
528 }, SecurityException.class);
530 assertException(new Invokable() {
532 public void run() throws Exception {
533 mIPrintManager.setPrintServiceEnabled(new ComponentName("bad", "name"), true,
536 }, SecurityException.class);
538 assertException(new Invokable() {
540 public void run() throws Exception {
541 mIPrintManager.setPrintServiceEnabled(null, true, mUserId);
543 }, SecurityException.class);
545 // Cannot test bad user Id as these tests are allowed to call across users
549 * test IPrintManager.createPrinterDiscoverySession
551 public void testCreatePrinterDiscoverySession() throws Exception {
552 final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
554 mIPrintManager.createPrinterDiscoverySession(listener, mUserId);
557 assertException(new Invokable() {
559 public void run() throws Exception {
560 mIPrintManager.createPrinterDiscoverySession(null, mUserId);
562 }, NullPointerException.class);
564 // Cannot test bad user Id as these tests are allowed to call across users
566 // Remove discovery session so that the next test create a new one. Usually a leaked
567 // session is removed on the next call from the print service. But in this case we want
568 // to force a new call to onPrinterDiscoverySessionStart in the next test.
569 mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
574 * test IPrintManager.startPrinterDiscovery
576 public void testStartPrinterDiscovery() throws Exception {
579 final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
580 final List<PrinterId> goodPrinters = new ArrayList<>();
581 goodPrinters.add(mGoodPrinterId);
583 final List<PrinterId> badPrinters = new ArrayList<>();
584 badPrinters.add(mBadPrinterId);
586 final List<PrinterId> emptyPrinters = new ArrayList<>();
588 final List<PrinterId> nullPrinters = new ArrayList<>();
589 nullPrinters.add(null);
591 mIPrintManager.startPrinterDiscovery(listener, goodPrinters, mUserId);
593 // Bad or no printers do no cause exceptions
594 mIPrintManager.startPrinterDiscovery(listener, badPrinters, mUserId);
595 mIPrintManager.startPrinterDiscovery(listener, emptyPrinters, mUserId);
596 mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
598 assertException(new Invokable() {
600 public void run() throws Exception {
601 mIPrintManager.startPrinterDiscovery(listener, nullPrinters, mUserId);
603 }, NullPointerException.class);
605 assertException(new Invokable() {
607 public void run() throws Exception {
608 mIPrintManager.startPrinterDiscovery(null, goodPrinters, mUserId);
610 }, NullPointerException.class);
612 // Cannot test bad user Id as these tests are allowed to call across users
616 * test IPrintManager.stopPrinterDiscovery
618 public void testStopPrinterDiscovery() throws Exception {
619 final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
621 mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
622 mIPrintManager.stopPrinterDiscovery(listener, mUserId);
624 // Stopping an already stopped session is a no-op
625 mIPrintManager.stopPrinterDiscovery(listener, mUserId);
627 mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
628 assertException(new Invokable() {
630 public void run() throws Exception {
631 mIPrintManager.stopPrinterDiscovery(null, mUserId);
633 }, NullPointerException.class);
635 // Cannot test bad user Id as these tests are allowed to call across users
639 * test IPrintManager.validatePrinters
641 public void testValidatePrinters() throws Exception {
644 final List<PrinterId> goodPrinters = new ArrayList<>();
645 goodPrinters.add(mGoodPrinterId);
647 final List<PrinterId> badPrinters = new ArrayList<>();
648 badPrinters.add(mBadPrinterId);
650 final List<PrinterId> emptyPrinters = new ArrayList<>();
652 final List<PrinterId> nullPrinters = new ArrayList<>();
653 nullPrinters.add(null);
655 mIPrintManager.validatePrinters(goodPrinters, mUserId);
657 // Bad or empty list of printers do no cause exceptions
658 mIPrintManager.validatePrinters(badPrinters, mUserId);
659 mIPrintManager.validatePrinters(emptyPrinters, mUserId);
661 assertException(new Invokable() {
663 public void run() throws Exception {
664 mIPrintManager.validatePrinters(null, mUserId);
666 }, NullPointerException.class);
668 assertException(new Invokable() {
670 public void run() throws Exception {
671 mIPrintManager.validatePrinters(nullPrinters, mUserId);
673 }, NullPointerException.class);
675 // Cannot test bad user Id as these tests are allowed to call across users
679 * test IPrintManager.startPrinterStateTracking
681 public void testStartPrinterStateTracking() throws Exception {
684 mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
686 // Bad printers do no cause exceptions
687 mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
689 assertException(new Invokable() {
691 public void run() throws Exception {
692 mIPrintManager.startPrinterStateTracking(null, mUserId);
694 }, NullPointerException.class);
696 // Cannot test bad user Id as these tests are allowed to call across users
700 * test IPrintManager.getCustomPrinterIcon
702 public void testGetCustomPrinterIcon() throws Exception {
705 mIPrintManager.getCustomPrinterIcon(mGoodPrinterId, mUserId);
707 // Bad printers do no cause exceptions
708 mIPrintManager.getCustomPrinterIcon(mBadPrinterId, mUserId);
710 assertException(new Invokable() {
712 public void run() throws Exception {
713 mIPrintManager.getCustomPrinterIcon(null, mUserId);
715 }, NullPointerException.class);
717 // Cannot test bad user Id as these tests are allowed to call across users
721 * test IPrintManager.stopPrinterStateTracking
723 public void testStopPrinterStateTracking() throws Exception {
726 mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
727 mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
729 // Stop to track a non-tracked printer is a no-op
730 mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
732 // Bad printers do no cause exceptions
733 mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
734 mIPrintManager.stopPrinterStateTracking(mBadPrinterId, mUserId);
736 assertException(new Invokable() {
738 public void run() throws Exception {
739 mIPrintManager.stopPrinterStateTracking(null, mUserId);
741 }, NullPointerException.class);
743 // Cannot test bad user Id as these tests are allowed to call across users
747 * test IPrintManager.destroyPrinterDiscoverySession
749 public void testDestroyPrinterDiscoverySession() throws Exception {
750 final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
752 mIPrintManager.createPrinterDiscoverySession(listener, mUserId);
753 mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
755 // Destroying already destroyed session is a no-op
756 mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
758 assertException(new Invokable() {
760 public void run() throws Exception {
761 mIPrintManager.destroyPrinterDiscoverySession(null, mUserId);
763 }, NullPointerException.class);
765 // Cannot test bad user Id as these tests are allowed to call across users