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
17package android.print;
18
19import android.annotation.NonNull;
20import android.content.ComponentName;
21import android.content.Context;
22import android.os.Bundle;
23import android.os.CancellationSignal;
24import android.os.Handler;
25import android.os.Looper;
26import android.os.ParcelFileDescriptor;
27import android.os.Process;
28import android.os.ServiceManager;
29import android.os.UserHandle;
30import android.print.PrintAttributes.Margins;
31import android.print.PrintAttributes.MediaSize;
32import android.print.PrintAttributes.Resolution;
33import android.printservice.PrintServiceInfo;
34import android.printservice.recommendation.IRecommendationsChangeListener;
35
36import android.print.mockservice.MockPrintService;
37import android.print.mockservice.PrintServiceCallbacks;
38import android.print.mockservice.PrinterDiscoverySessionCallbacks;
39import android.print.mockservice.StubbablePrinterDiscoverySession;
40
41import android.test.suitebuilder.annotation.LargeTest;
42import android.test.suitebuilder.annotation.MediumTest;
43import org.mockito.invocation.InvocationOnMock;
44import org.mockito.stubbing.Answer;
45
46import java.util.ArrayList;
47import java.util.List;
48
49/**
50 * tests feeding all possible parameters to the IPrintManager Binder.
51 */
52public class IPrintManagerParametersTest extends BasePrintTest {
53
54    private final int BAD_APP_ID = 0xffffffff;
55
56    private final int mAppId;
57    private final int mUserId;
58    private final PrintJobId mBadPrintJobId;
59
60    private PrintJob mGoodPrintJob;
61    private PrinterId mBadPrinterId;
62    private PrinterId mGoodPrinterId;
63    private ComponentName mGoodComponentName;
64    private ComponentName mBadComponentName;
65
66    private IPrintManager mIPrintManager;
67
68    /**
69     * Create a new IPrintManagerParametersTest and setup basic fields.
70     */
71    public IPrintManagerParametersTest() {
72        super();
73
74        mAppId = UserHandle.getAppId(Process.myUid());
75        mUserId = UserHandle.myUserId();
76        mBadPrintJobId = new PrintJobId();
77        mBadComponentName = new ComponentName("bad", "bad");
78    }
79
80    /**
81     * Create a mock PrintDocumentAdapter.
82     *
83     * @return The adapter
84     */
85    private @NonNull PrintDocumentAdapter createMockAdapter() {
86        return new PrintDocumentAdapter() {
87            @Override
88            public void onStart() {
89                onStartCalled();
90            }
91
92            @Override
93            public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
94                    CancellationSignal cancellationSignal, LayoutResultCallback callback,
95                    Bundle extras) {
96            }
97
98            @Override
99            public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
100                    CancellationSignal cancellationSignal, WriteResultCallback callback) {
101            }
102        };
103    }
104
105    /**
106     * Create mock print service callbacks.
107     *
108     * @return the callbacks
109     */
110    private PrintServiceCallbacks createMockCallbacks() {
111        return createMockPrintServiceCallbacks(
112                new Answer<PrinterDiscoverySessionCallbacks>() {
113                    @Override
114                    public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
115                        return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
116                            @Override
117                            public Void answer(InvocationOnMock invocation) {
118                                // Get the session.
119                                StubbablePrinterDiscoverySession session =
120                                        ((PrinterDiscoverySessionCallbacks) invocation
121                                        .getMock()).getSession();
122
123                                if (session.getPrinters().isEmpty()) {
124                                    final String PRINTER_NAME = "good printer";
125                                    List<PrinterInfo> printers = new ArrayList<>();
126
127                                    // Add the printer.
128                                    mGoodPrinterId = session.getService()
129                                            .generatePrinterId(PRINTER_NAME);
130
131                                    PrinterCapabilitiesInfo capabilities =
132                                            new PrinterCapabilitiesInfo.Builder(mGoodPrinterId)
133                                                    .setMinMargins(
134                                                            new Margins(200, 200, 200, 200))
135                                                    .addMediaSize(MediaSize.ISO_A4, true)
136                                                    .addResolution(new Resolution("300x300",
137                                                            "300x300", 300, 300),
138                                                            true)
139                                                    .setColorModes(
140                                                            PrintAttributes.COLOR_MODE_COLOR,
141                                                            PrintAttributes.COLOR_MODE_COLOR)
142                                                    .build();
143
144                                    PrinterInfo printer = new PrinterInfo.Builder(
145                                            mGoodPrinterId,
146                                            PRINTER_NAME,
147                                            PrinterInfo.STATUS_IDLE)
148                                                    .setCapabilities(capabilities)
149                                                    .build();
150                                    printers.add(printer);
151
152                                    session.addPrinters(printers);
153                                }
154                                onPrinterDiscoverySessionStartCalled();
155                                return null;
156                            }
157                        }, null, null, null, null, null, null);
158                    }
159                },
160                null, null);
161    }
162
163    /**
164     * Create a IPrintJobStateChangeListener object.
165     *
166     * @return the object
167     * @throws Exception if the object could not be created.
168     */
169    private IPrintJobStateChangeListener createMockIPrintJobStateChangeListener() throws Exception {
170        return new PrintManager.PrintJobStateChangeListenerWrapper(null,
171                new Handler(Looper.getMainLooper()));
172    }
173
174    /**
175     * Create a IPrintServicesChangeListener object.
176     *
177     * @return the object
178     * @throws Exception if the object could not be created.
179     */
180    private IPrintServicesChangeListener createMockIPrintServicesChangeListener() throws Exception {
181        return new PrintManager.PrintServicesChangeListenerWrapper(null,
182                new Handler(Looper.getMainLooper()));
183    }
184
185    /**
186     * Create a IPrintServiceRecommendationsChangeListener object.
187     *
188     * @return the object
189     * @throws Exception if the object could not be created.
190     */
191    private IRecommendationsChangeListener
192    createMockIPrintServiceRecommendationsChangeListener() throws Exception {
193        return new PrintManager.PrintServiceRecommendationsChangeListenerWrapper(null,
194                new Handler(Looper.getMainLooper()));
195    }
196
197    /**
198     * Create a IPrinterDiscoveryObserver object.
199     *
200     * @return the object
201     * @throws Exception if the object could not be created.
202     */
203    private IPrinterDiscoveryObserver createMockIPrinterDiscoveryObserver() throws Exception {
204        return new PrinterDiscoverySession.PrinterDiscoveryObserver(null);
205    }
206
207    private void startPrinting() {
208        mGoodPrintJob = print(createMockAdapter(), null);
209
210        // Wait for PrintActivity to be ready
211        waitForStartAdapterCallbackCalled();
212
213        // Wait for printer discovery session to be ready
214        waitForPrinterDiscoverySessionStartCallbackCalled();
215    }
216
217    @Override
218    public void setUp() throws Exception {
219        super.setUp();
220
221        MockPrintService.setCallbacks(createMockCallbacks());
222
223        mGoodComponentName = getActivity().getComponentName();
224
225        mIPrintManager = IPrintManager.Stub
226                .asInterface(ServiceManager.getService(Context.PRINT_SERVICE));
227
228        // Generate dummy printerId which is a valid PrinterId object, but does not correspond to a
229        // printer
230        mBadPrinterId = new PrinterId(mGoodComponentName, "dummy printer");
231    }
232
233    /**
234     * {@link Runnable} that can throw and {@link Exception}
235     */
236    private interface Invokable {
237        /**
238         * Execute the invokable
239         *
240         * @throws Exception
241         */
242        void run() throws Exception;
243    }
244
245    /**
246     * Assert that the invokable throws an expectedException
247     *
248     * @param invokable The {@link Invokable} to run
249     * @param expectedClass The {@link Exception} that is supposed to be thrown
250     */
251    public void assertException(Invokable invokable, Class<? extends Exception> expectedClass)
252            throws Exception {
253        try {
254            invokable.run();
255        } catch (Exception e) {
256            if (e.getClass().isAssignableFrom(expectedClass)) {
257                return;
258            } else {
259                throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
260                                + e.getClass().getName());
261            }
262        }
263
264        throw new AssertionError("No exception thrown");
265    }
266
267    /**
268     * test IPrintManager.getPrintJobInfo
269     */
270    @LargeTest
271    public void testGetPrintJobInfo() throws Exception {
272        startPrinting();
273
274        assertEquals(mGoodPrintJob.getId(), mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(),
275                        mAppId, mUserId).getId());
276        assertEquals(null, mIPrintManager.getPrintJobInfo(mBadPrintJobId, mAppId, mUserId));
277        assertEquals(null, mIPrintManager.getPrintJobInfo(null, mAppId, mUserId));
278
279        assertException(new Invokable() {
280            @Override
281            public void run() throws Exception {
282                mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
283            }
284        }, SecurityException.class);
285
286        // Cannot test bad user Id as these tests are allowed to call across users
287    }
288
289    /**
290     * test IPrintManager.getPrintJobInfos
291     */
292    @LargeTest
293    public void testGetPrintJobInfos() throws Exception {
294        startPrinting();
295
296        List<PrintJobInfo> infos = mIPrintManager.getPrintJobInfos(mAppId, mUserId);
297
298        boolean foundPrintJob = false;
299        for (PrintJobInfo info : infos) {
300            if (info.getId().equals(mGoodPrintJob.getId())) {
301                assertEquals(PrintJobInfo.STATE_CREATED, info.getState());
302                foundPrintJob = true;
303            }
304        }
305        assertTrue(foundPrintJob);
306
307        assertException(new Invokable() {
308            @Override
309            public void run() throws Exception {
310                mIPrintManager.getPrintJobInfos(BAD_APP_ID, mUserId);
311            }
312        }, SecurityException.class);
313
314        // Cannot test bad user Id as these tests are allowed to call across users
315    }
316
317    /**
318     * test IPrintManager.print
319     */
320    @LargeTest
321    public void testPrint() throws Exception {
322        final String name = "dummy print job";
323
324        final IPrintDocumentAdapter adapter = new PrintManager
325                .PrintDocumentAdapterDelegate(getActivity(), createMockAdapter());
326
327        startPrinting();
328
329        assertException(new Invokable() {
330            @Override
331            public void run() throws Exception {
332                mIPrintManager.print(null, adapter, null, mGoodComponentName.getPackageName(),
333                        mAppId, mUserId);
334            }
335        }, IllegalArgumentException.class);
336
337        assertException(new Invokable() {
338            @Override
339            public void run() throws Exception {
340                mIPrintManager.print(name, null, null, mGoodComponentName.getPackageName(),
341                        mAppId, mUserId);
342            }
343        }, NullPointerException.class);
344
345        assertException(new Invokable() {
346            @Override
347            public void run() throws Exception {
348                mIPrintManager.print(name, adapter, null, null, mAppId, mUserId);
349            }
350        }, IllegalArgumentException.class);
351
352        assertException(new Invokable() {
353            @Override
354            public void run() throws Exception {
355                mIPrintManager.print(name, adapter, null, mBadComponentName.getPackageName(),
356                        mAppId, mUserId);
357            }
358        }, IllegalArgumentException.class);
359
360        assertException(new Invokable() {
361            @Override
362            public void run() throws Exception {
363                mIPrintManager.print(name, adapter, null, mGoodComponentName.getPackageName(),
364                        BAD_APP_ID, mUserId);
365            }
366        }, SecurityException.class);
367
368        // Cannot test bad user Id as these tests are allowed to call across users
369    }
370
371    /**
372     * test IPrintManager.cancelPrintJob
373     */
374    @LargeTest
375    public void testCancelPrintJob() throws Exception {
376        startPrinting();
377
378        // Invalid print jobs IDs do not produce an exception
379        mIPrintManager.cancelPrintJob(mBadPrintJobId, mAppId, mUserId);
380        mIPrintManager.cancelPrintJob(null, mAppId, mUserId);
381
382        assertException(new Invokable() {
383            @Override
384            public void run() throws Exception {
385                mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
386            }
387        }, SecurityException.class);
388
389        // Cannot test bad user Id as these tests are allowed to call across users
390
391        // Must be last as otherwise mGoodPrintJob will not be good anymore
392        mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), mAppId, mUserId);
393    }
394
395    /**
396     * test IPrintManager.restartPrintJob
397     */
398    @LargeTest
399    public void testRestartPrintJob() throws Exception {
400        startPrinting();
401
402        mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), mAppId, mUserId);
403
404        // Invalid print jobs IDs do not produce an exception
405        mIPrintManager.restartPrintJob(mBadPrintJobId, mAppId, mUserId);
406        mIPrintManager.restartPrintJob(null, mAppId, mUserId);
407
408        assertException(new Invokable() {
409            @Override
410            public void run() throws Exception {
411                mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
412            }
413        }, SecurityException.class);
414
415        // Cannot test bad user Id as these tests are allowed to call across users
416    }
417
418    /**
419     * test IPrintManager.addPrintJobStateChangeListener
420     */
421    @MediumTest
422    public void testAddPrintJobStateChangeListener() throws Exception {
423        final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
424
425        mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
426
427        assertException(new Invokable() {
428            @Override
429            public void run() throws Exception {
430                mIPrintManager.addPrintJobStateChangeListener(null, mAppId, mUserId);
431            }
432        }, NullPointerException.class);
433
434        assertException(new Invokable() {
435            @Override
436            public void run() throws Exception {
437                mIPrintManager.addPrintJobStateChangeListener(listener, BAD_APP_ID, mUserId);
438            }
439        }, SecurityException.class);
440
441        // Cannot test bad user Id as these tests are allowed to call across users
442    }
443
444    /**
445     * test IPrintManager.removePrintJobStateChangeListener
446     */
447    @MediumTest
448    public void testRemovePrintJobStateChangeListener() throws Exception {
449        final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
450
451        mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
452        mIPrintManager.removePrintJobStateChangeListener(listener, mUserId);
453
454        // Removing unknown listeners is a no-op
455        mIPrintManager.removePrintJobStateChangeListener(listener, mUserId);
456
457        mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
458        assertException(new Invokable() {
459            @Override
460            public void run() throws Exception {
461                mIPrintManager.removePrintJobStateChangeListener(null, mUserId);
462            }
463        }, NullPointerException.class);
464
465        // Cannot test bad user Id as these tests are allowed to call across users
466    }
467
468    /**
469     * test IPrintManager.addPrintServicesChangeListener
470     */
471    @MediumTest
472    public void testAddPrintServicesChangeListener() throws Exception {
473        final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
474
475        mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
476
477        assertException(new Invokable() {
478            @Override
479            public void run() throws Exception {
480                mIPrintManager.addPrintServicesChangeListener(null, mUserId);
481            }
482        }, NullPointerException.class);
483
484        // Cannot test bad user Id as these tests are allowed to call across users
485    }
486
487    /**
488     * test IPrintManager.removePrintServicesChangeListener
489     */
490    @MediumTest
491    public void testRemovePrintServicesChangeListener() throws Exception {
492        final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
493
494        mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
495        mIPrintManager.removePrintServicesChangeListener(listener, mUserId);
496
497        // Removing unknown listeners is a no-op
498        mIPrintManager.removePrintServicesChangeListener(listener, mUserId);
499
500        mIPrintManager.addPrintServicesChangeListener(listener, mUserId);
501        assertException(new Invokable() {
502            @Override
503            public void run() throws Exception {
504                mIPrintManager.removePrintServicesChangeListener(null, mUserId);
505            }
506        }, NullPointerException.class);
507
508        // Cannot test bad user Id as these tests are allowed to call across users
509    }
510
511    /**
512     * test IPrintManager.getPrintServices
513     */
514    @MediumTest
515    public void testGetPrintServices() throws Exception {
516        List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
517                PrintManager.ALL_SERVICES, mUserId);
518        assertTrue(printServices.size() >= 1);
519
520        printServices = mIPrintManager.getPrintServices(0, mUserId);
521        assertEquals(printServices, null);
522
523        assertException(new Invokable() {
524            @Override
525            public void run() throws Exception {
526                mIPrintManager.getPrintServices(~PrintManager.ALL_SERVICES, mUserId);
527            }
528        }, IllegalArgumentException.class);
529
530        // Cannot test bad user Id as these tests are allowed to call across users
531    }
532
533    /**
534     * test IPrintManager.setPrintServiceEnabled
535     */
536    @MediumTest
537    public void testSetPrintServiceEnabled() throws Exception {
538        final ComponentName printService = mIPrintManager.getPrintServices(
539                PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
540
541        assertException(new Invokable() {
542            @Override
543            public void run() throws Exception {
544                mIPrintManager.setPrintServiceEnabled(printService, false, mUserId);
545            }
546        }, SecurityException.class);
547
548        assertException(new Invokable() {
549            @Override
550            public void run() throws Exception {
551                mIPrintManager.setPrintServiceEnabled(printService, true, mUserId);
552            }
553        }, SecurityException.class);
554
555        assertException(new Invokable() {
556            @Override
557            public void run() throws Exception {
558                mIPrintManager.setPrintServiceEnabled(new ComponentName("bad", "name"), true,
559                                mUserId);
560            }
561        }, SecurityException.class);
562
563        assertException(new Invokable() {
564            @Override
565            public void run() throws Exception {
566                mIPrintManager.setPrintServiceEnabled(null, true, mUserId);
567            }
568        }, SecurityException.class);
569
570        // Cannot test bad user Id as these tests are allowed to call across users
571    }
572
573    /**
574     * test IPrintManager.addPrintServiceRecommendationsChangeListener
575     */
576    @MediumTest
577    public void testAddPrintServiceRecommendationsChangeListener() throws Exception {
578        final IRecommendationsChangeListener listener =
579                createMockIPrintServiceRecommendationsChangeListener();
580
581        mIPrintManager.addPrintServiceRecommendationsChangeListener(listener, mUserId);
582
583        assertException(new Invokable() {
584            @Override
585            public void run() throws Exception {
586                mIPrintManager.addPrintServiceRecommendationsChangeListener(null, mUserId);
587            }
588        }, NullPointerException.class);
589
590        // Cannot test bad user Id as these tests are allowed to call across users
591    }
592
593    /**
594     * test IPrintManager.removePrintServicesChangeListener
595     */
596    @MediumTest
597    public void testRemovePrintServiceRecommendationsChangeListener() throws Exception {
598        final IRecommendationsChangeListener listener =
599                createMockIPrintServiceRecommendationsChangeListener();
600
601        mIPrintManager.addPrintServiceRecommendationsChangeListener(listener, mUserId);
602        mIPrintManager.removePrintServiceRecommendationsChangeListener(listener, mUserId);
603
604        // Removing unknown listeners is a no-op
605        mIPrintManager.removePrintServiceRecommendationsChangeListener(listener, mUserId);
606
607        mIPrintManager.addPrintServiceRecommendationsChangeListener(listener, mUserId);
608        assertException(new Invokable() {
609            @Override
610            public void run() throws Exception {
611                mIPrintManager.removePrintServiceRecommendationsChangeListener(null, mUserId);
612            }
613        }, NullPointerException.class);
614
615        // Cannot test bad user Id as these tests are allowed to call across users
616    }
617
618    /**
619     * test IPrintManager.getPrintServiceRecommendations
620     */
621    @MediumTest
622    public void testGetPrintServiceRecommendations() throws Exception {
623        mIPrintManager.getPrintServiceRecommendations(mUserId);
624
625        // Cannot test bad user Id as these tests are allowed to call across users
626    }
627
628    /**
629     * test IPrintManager.createPrinterDiscoverySession
630     */
631    @MediumTest
632    public void testCreatePrinterDiscoverySession() throws Exception {
633        final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
634
635        mIPrintManager.createPrinterDiscoverySession(listener, mUserId);
636
637        try {
638            assertException(new Invokable() {
639                @Override
640                public void run() throws Exception {
641                    mIPrintManager.createPrinterDiscoverySession(null, mUserId);
642                }
643            }, NullPointerException.class);
644
645            // Cannot test bad user Id as these tests are allowed to call across users
646        } finally {
647            // Remove discovery session so that the next test create a new one. Usually a leaked
648            // session is removed on the next call from the print service. But in this case we want
649            // to force a new call to onPrinterDiscoverySessionStart in the next test.
650            mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
651        }
652    }
653
654    /**
655     * test IPrintManager.startPrinterDiscovery
656     */
657    @LargeTest
658    public void testStartPrinterDiscovery() throws Exception {
659        startPrinting();
660
661        final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
662        final List<PrinterId> goodPrinters = new ArrayList<>();
663        goodPrinters.add(mGoodPrinterId);
664
665        final List<PrinterId> badPrinters = new ArrayList<>();
666        badPrinters.add(mBadPrinterId);
667
668        final List<PrinterId> emptyPrinters = new ArrayList<>();
669
670        final List<PrinterId> nullPrinters = new ArrayList<>();
671        nullPrinters.add(null);
672
673        mIPrintManager.startPrinterDiscovery(listener, goodPrinters, mUserId);
674
675        // Bad or no printers do no cause exceptions
676        mIPrintManager.startPrinterDiscovery(listener, badPrinters, mUserId);
677        mIPrintManager.startPrinterDiscovery(listener, emptyPrinters, mUserId);
678        mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
679
680        assertException(new Invokable() {
681            @Override
682            public void run() throws Exception {
683                mIPrintManager.startPrinterDiscovery(listener, nullPrinters, mUserId);
684            }
685        }, NullPointerException.class);
686
687        assertException(new Invokable() {
688            @Override
689            public void run() throws Exception {
690                mIPrintManager.startPrinterDiscovery(null, goodPrinters, mUserId);
691            }
692        }, NullPointerException.class);
693
694        // Cannot test bad user Id as these tests are allowed to call across users
695    }
696
697    /**
698     * test IPrintManager.stopPrinterDiscovery
699     */
700    @MediumTest
701    public void testStopPrinterDiscovery() throws Exception {
702        final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
703
704        mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
705        mIPrintManager.stopPrinterDiscovery(listener, mUserId);
706
707        // Stopping an already stopped session is a no-op
708        mIPrintManager.stopPrinterDiscovery(listener, mUserId);
709
710        mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
711        assertException(new Invokable() {
712            @Override
713            public void run() throws Exception {
714                mIPrintManager.stopPrinterDiscovery(null, mUserId);
715            }
716        }, NullPointerException.class);
717
718        // Cannot test bad user Id as these tests are allowed to call across users
719    }
720
721    /**
722     * test IPrintManager.validatePrinters
723     */
724    @LargeTest
725    public void testValidatePrinters() throws Exception {
726        startPrinting();
727
728        final List<PrinterId> goodPrinters = new ArrayList<>();
729        goodPrinters.add(mGoodPrinterId);
730
731        final List<PrinterId> badPrinters = new ArrayList<>();
732        badPrinters.add(mBadPrinterId);
733
734        final List<PrinterId> emptyPrinters = new ArrayList<>();
735
736        final List<PrinterId> nullPrinters = new ArrayList<>();
737        nullPrinters.add(null);
738
739        mIPrintManager.validatePrinters(goodPrinters, mUserId);
740
741        // Bad or empty list of printers do no cause exceptions
742        mIPrintManager.validatePrinters(badPrinters, mUserId);
743        mIPrintManager.validatePrinters(emptyPrinters, mUserId);
744
745        assertException(new Invokable() {
746            @Override
747            public void run() throws Exception {
748                mIPrintManager.validatePrinters(null, mUserId);
749            }
750        }, NullPointerException.class);
751
752        assertException(new Invokable() {
753            @Override
754            public void run() throws Exception {
755                mIPrintManager.validatePrinters(nullPrinters, mUserId);
756            }
757        }, NullPointerException.class);
758
759        // Cannot test bad user Id as these tests are allowed to call across users
760    }
761
762    /**
763     * test IPrintManager.startPrinterStateTracking
764     */
765    @LargeTest
766    public void testStartPrinterStateTracking() throws Exception {
767        startPrinting();
768
769        mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
770
771        // Bad printers do no cause exceptions
772        mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
773
774        assertException(new Invokable() {
775            @Override
776            public void run() throws Exception {
777                mIPrintManager.startPrinterStateTracking(null, mUserId);
778            }
779        }, NullPointerException.class);
780
781        // Cannot test bad user Id as these tests are allowed to call across users
782    }
783
784    /**
785     * test IPrintManager.getCustomPrinterIcon
786     */
787    @LargeTest
788    public void testGetCustomPrinterIcon() throws Exception {
789        startPrinting();
790
791        mIPrintManager.getCustomPrinterIcon(mGoodPrinterId, mUserId);
792
793        // Bad printers do no cause exceptions
794        mIPrintManager.getCustomPrinterIcon(mBadPrinterId, mUserId);
795
796        assertException(new Invokable() {
797            @Override
798            public void run() throws Exception {
799                mIPrintManager.getCustomPrinterIcon(null, mUserId);
800            }
801        }, NullPointerException.class);
802
803        // Cannot test bad user Id as these tests are allowed to call across users
804    }
805
806    /**
807     * test IPrintManager.stopPrinterStateTracking
808     */
809    @LargeTest
810    public void testStopPrinterStateTracking() throws Exception {
811        startPrinting();
812
813        mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
814        mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
815
816        // Stop to track a non-tracked printer is a no-op
817        mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
818
819        // Bad printers do no cause exceptions
820        mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
821        mIPrintManager.stopPrinterStateTracking(mBadPrinterId, mUserId);
822
823        assertException(new Invokable() {
824            @Override
825            public void run() throws Exception {
826                mIPrintManager.stopPrinterStateTracking(null, mUserId);
827            }
828        }, NullPointerException.class);
829
830        // Cannot test bad user Id as these tests are allowed to call across users
831    }
832
833    /**
834     * test IPrintManager.destroyPrinterDiscoverySession
835     */
836    @MediumTest
837    public void testDestroyPrinterDiscoverySession() throws Exception {
838        final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
839
840        mIPrintManager.createPrinterDiscoverySession(listener, mUserId);
841        mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
842
843        // Destroying already destroyed session is a no-op
844        mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
845
846        assertException(new Invokable() {
847            @Override
848            public void run() throws Exception {
849                mIPrintManager.destroyPrinterDiscoverySession(null, mUserId);
850            }
851        }, NullPointerException.class);
852
853        // Cannot test bad user Id as these tests are allowed to call across users
854    }
855}
856