Merge "Check parameters for callers of IPrintManager"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e33b954165
@@ -535,7 +535,10 @@ public final class PrintManager {
|
||||
return new PrinterDiscoverySession(mService, mContext, mUserId);
|
||||
}
|
||||
|
||||
private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub
|
||||
implements ActivityLifecycleCallbacks {
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@@ -1061,7 +1064,10 @@ public final class PrintManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PrintJobStateChangeListenerWrapper extends
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final class PrintJobStateChangeListenerWrapper extends
|
||||
IPrintJobStateChangeListener.Stub {
|
||||
private final WeakReference<PrintJobStateChangeListener> mWeakListener;
|
||||
private final WeakReference<Handler> mWeakHandler;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.print;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.Handler;
|
||||
@@ -72,7 +74,7 @@ public final class PrinterDiscoverySession {
|
||||
}
|
||||
}
|
||||
|
||||
public final void startPrinterDiscovery(List<PrinterId> priorityList) {
|
||||
public final void startPrinterDiscovery(@Nullable List<PrinterId> priorityList) {
|
||||
if (isDestroyed()) {
|
||||
Log.w(LOG_TAG, "Ignoring start printers discovery - session destroyed");
|
||||
return;
|
||||
@@ -102,7 +104,7 @@ public final class PrinterDiscoverySession {
|
||||
}
|
||||
}
|
||||
|
||||
public final void startPrinterStateTracking(PrinterId printerId) {
|
||||
public final void startPrinterStateTracking(@NonNull PrinterId printerId) {
|
||||
if (isDestroyed()) {
|
||||
Log.w(LOG_TAG, "Ignoring start printer state tracking - session destroyed");
|
||||
return;
|
||||
@@ -114,7 +116,7 @@ public final class PrinterDiscoverySession {
|
||||
}
|
||||
}
|
||||
|
||||
public final void stopPrinterStateTracking(PrinterId printerId) {
|
||||
public final void stopPrinterStateTracking(@NonNull PrinterId printerId) {
|
||||
if (isDestroyed()) {
|
||||
Log.w(LOG_TAG, "Ignoring stop printer state tracking - session destroyed");
|
||||
return;
|
||||
@@ -285,7 +287,7 @@ public final class PrinterDiscoverySession {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub {
|
||||
public static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub {
|
||||
|
||||
private final WeakReference<PrinterDiscoverySession> mWeakSession;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.printservice;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
@@ -346,7 +347,7 @@ public abstract class PrintService extends Service {
|
||||
* @param localId A locally unique id in the context of your print service.
|
||||
* @return Global printer id.
|
||||
*/
|
||||
public final PrinterId generatePrinterId(String localId) {
|
||||
public @NonNull final PrinterId generatePrinterId(String localId) {
|
||||
throwIfNotCalledOnMainThread();
|
||||
localId = Preconditions.checkNotNull(localId, "localId cannot be null");
|
||||
return new PrinterId(new ComponentName(getPackageName(),
|
||||
|
||||
@@ -42,6 +42,23 @@ public class Preconditions {
|
||||
* @return the string reference that was validated
|
||||
* @throws IllegalArgumentException if {@code string} is empty
|
||||
*/
|
||||
public static @NonNull String checkStringNotEmpty(final String string) {
|
||||
if (TextUtils.isEmpty(string)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that an string reference passed as a parameter to the calling
|
||||
* method is not empty.
|
||||
*
|
||||
* @param string an string reference
|
||||
* @param errorMessage the exception message to use if the check fails; will
|
||||
* be converted to a string using {@link String#valueOf(Object)}
|
||||
* @return the string reference that was validated
|
||||
* @throws IllegalArgumentException if {@code string} is empty
|
||||
*/
|
||||
public static @NonNull String checkStringNotEmpty(final String string,
|
||||
final Object errorMessage) {
|
||||
if (TextUtils.isEmpty(string)) {
|
||||
@@ -301,8 +318,8 @@ public class Preconditions {
|
||||
*
|
||||
* @throws NullPointerException if the {@code value} or any of its elements were {@code null}
|
||||
*/
|
||||
public static <T> Collection<T> checkCollectionElementsNotNull(final Collection<T> value,
|
||||
final String valueName) {
|
||||
public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
|
||||
final C value, final String valueName) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException(valueName + " must not be null");
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
littlemock \
|
||||
android-support-test \
|
||||
mockito-target \
|
||||
espresso-core
|
||||
espresso-core \
|
||||
ub-uiautomator
|
||||
LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy
|
||||
LOCAL_PACKAGE_NAME := FrameworksCoreTests
|
||||
|
||||
|
||||
@@ -1295,6 +1295,26 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="android.print.PrintTestActivity"/>
|
||||
|
||||
<service
|
||||
android:name="android.print.mockservice.MockPrintService"
|
||||
android:permission="android.permission.BIND_PRINT_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.printservice.PrintService" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.printservice"
|
||||
android:resource="@xml/printservice">
|
||||
</meta-data>
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name="android.print.mockservice.SettingsActivity"
|
||||
android:permission="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
|
||||
android:exported="true">
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
20
core/tests/coretests/res/xml/printservice.xml
Normal file
20
core/tests/coretests/res/xml/printservice.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<print-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:settingsActivity="android.print.mockservice.SettingsActivity"/>
|
||||
361
core/tests/coretests/src/android/print/BasePrintTest.java
Normal file
361
core/tests/coretests/src/android/print/BasePrintTest.java
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.SystemClock;
|
||||
import android.print.PrintAttributes;
|
||||
import android.print.PrintDocumentAdapter;
|
||||
import android.print.PrintManager;
|
||||
import android.print.PrinterId;
|
||||
import android.print.mockservice.PrintServiceCallbacks;
|
||||
import android.print.mockservice.PrinterDiscoverySessionCallbacks;
|
||||
import android.print.mockservice.StubbablePrinterDiscoverySession;
|
||||
import android.printservice.CustomPrinterIconCallback;
|
||||
import android.printservice.PrintJob;
|
||||
import android.printservice.PrintService;
|
||||
import android.test.InstrumentationTestCase;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.LocaleList;
|
||||
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* This is the base class for print tests.
|
||||
*/
|
||||
public abstract class BasePrintTest extends InstrumentationTestCase {
|
||||
|
||||
private static final long OPERATION_TIMEOUT = 30000;
|
||||
private static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";
|
||||
private static final String PM_CLEAR_SUCCESS_OUTPUT = "Success";
|
||||
private static final String COMMAND_LIST_ENABLED_IME_COMPONENTS = "ime list -s";
|
||||
private static final String COMMAND_PREFIX_ENABLE_IME = "ime enable ";
|
||||
private static final String COMMAND_PREFIX_DISABLE_IME = "ime disable ";
|
||||
private static final int CURRENT_USER_ID = -2; // Mirrors UserHandle.USER_CURRENT
|
||||
|
||||
private PrintTestActivity mActivity;
|
||||
private android.print.PrintJob mPrintJob;
|
||||
|
||||
private LocaleList mOldLocale;
|
||||
|
||||
private CallCounter mStartCallCounter;
|
||||
private CallCounter mStartSessionCallCounter;
|
||||
|
||||
private String[] mEnabledImes;
|
||||
|
||||
private String[] getEnabledImes() throws IOException {
|
||||
List<String> imeList = new ArrayList<>();
|
||||
|
||||
ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
|
||||
.executeShellCommand(COMMAND_LIST_ENABLED_IME_COMPONENTS);
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(pfd.getFileDescriptor())))) {
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
imeList.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
String[] imeArray = new String[imeList.size()];
|
||||
imeList.toArray(imeArray);
|
||||
|
||||
return imeArray;
|
||||
}
|
||||
|
||||
private void disableImes() throws Exception {
|
||||
mEnabledImes = getEnabledImes();
|
||||
for (String ime : mEnabledImes) {
|
||||
String disableImeCommand = COMMAND_PREFIX_DISABLE_IME + ime;
|
||||
runShellCommand(getInstrumentation(), disableImeCommand);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableImes() throws Exception {
|
||||
for (String ime : mEnabledImes) {
|
||||
String enableImeCommand = COMMAND_PREFIX_ENABLE_IME + ime;
|
||||
runShellCommand(getInstrumentation(), enableImeCommand);
|
||||
}
|
||||
mEnabledImes = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runTest() throws Throwable {
|
||||
// Do nothing if the device does not support printing.
|
||||
if (supportsPrinting()) {
|
||||
super.runTest();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
if (!supportsPrinting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we start with a clean slate.
|
||||
clearPrintSpoolerData();
|
||||
disableImes();
|
||||
|
||||
// Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
|
||||
// Dexmaker is used by mockito.
|
||||
System.setProperty("dexmaker.dexcache", getInstrumentation()
|
||||
.getTargetContext().getCacheDir().getPath());
|
||||
|
||||
// Set to US locale.
|
||||
Resources resources = getInstrumentation().getTargetContext().getResources();
|
||||
Configuration oldConfiguration = resources.getConfiguration();
|
||||
if (!oldConfiguration.getLocales().getPrimary().equals(Locale.US)) {
|
||||
mOldLocale = oldConfiguration.getLocales();
|
||||
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
|
||||
Configuration newConfiguration = new Configuration(oldConfiguration);
|
||||
newConfiguration.setLocale(Locale.US);
|
||||
resources.updateConfiguration(newConfiguration, displayMetrics);
|
||||
}
|
||||
|
||||
// Initialize the latches.
|
||||
mStartCallCounter = new CallCounter();
|
||||
mStartSessionCallCounter = new CallCounter();
|
||||
|
||||
// Create the activity for the right locale.
|
||||
createActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
if (!supportsPrinting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Done with the activity.
|
||||
getActivity().finish();
|
||||
enableImes();
|
||||
|
||||
// Restore the locale if needed.
|
||||
if (mOldLocale != null) {
|
||||
Resources resources = getInstrumentation().getTargetContext().getResources();
|
||||
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
|
||||
Configuration newConfiguration = new Configuration(resources.getConfiguration());
|
||||
newConfiguration.setLocales(mOldLocale);
|
||||
mOldLocale = null;
|
||||
resources.updateConfiguration(newConfiguration, displayMetrics);
|
||||
}
|
||||
|
||||
// Make sure the spooler is cleaned, this also un-approves all services
|
||||
clearPrintSpoolerData();
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected android.print.PrintJob print(@NonNull final PrintDocumentAdapter adapter,
|
||||
final PrintAttributes attributes) {
|
||||
// Initiate printing as if coming from the app.
|
||||
getInstrumentation().runOnMainSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PrintManager printManager = (PrintManager) getActivity()
|
||||
.getSystemService(Context.PRINT_SERVICE);
|
||||
mPrintJob = printManager.print("Print job", adapter, attributes);
|
||||
}
|
||||
});
|
||||
|
||||
return mPrintJob;
|
||||
}
|
||||
|
||||
protected void onStartCalled() {
|
||||
mStartCallCounter.call();
|
||||
}
|
||||
|
||||
protected void onPrinterDiscoverySessionStartCalled() {
|
||||
mStartSessionCallCounter.call();
|
||||
}
|
||||
|
||||
protected void waitForPrinterDiscoverySessionStartCallbackCalled() {
|
||||
waitForCallbackCallCount(mStartSessionCallCounter, 1,
|
||||
"Did not get expected call to onStartPrinterDiscoverySession.");
|
||||
}
|
||||
|
||||
protected void waitForStartAdapterCallbackCalled() {
|
||||
waitForCallbackCallCount(mStartCallCounter, 1, "Did not get expected call to start.");
|
||||
}
|
||||
|
||||
private void waitForCallbackCallCount(CallCounter counter, int count, String message) {
|
||||
try {
|
||||
counter.waitForCount(count, OPERATION_TIMEOUT);
|
||||
} catch (TimeoutException te) {
|
||||
fail(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected PrintTestActivity getActivity() {
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
protected void createActivity() {
|
||||
mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
|
||||
PrintTestActivity.class, null);
|
||||
}
|
||||
|
||||
public static String runShellCommand(Instrumentation instrumentation, String cmd)
|
||||
throws IOException {
|
||||
ParcelFileDescriptor pfd = instrumentation.getUiAutomation().executeShellCommand(cmd);
|
||||
byte[] buf = new byte[512];
|
||||
int bytesRead;
|
||||
FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
|
||||
StringBuffer stdout = new StringBuffer();
|
||||
while ((bytesRead = fis.read(buf)) != -1) {
|
||||
stdout.append(new String(buf, 0, bytesRead));
|
||||
}
|
||||
fis.close();
|
||||
return stdout.toString();
|
||||
}
|
||||
|
||||
protected void clearPrintSpoolerData() throws Exception {
|
||||
assertTrue("failed to clear print spooler data",
|
||||
runShellCommand(getInstrumentation(), String.format(
|
||||
"pm clear --user %d %s", CURRENT_USER_ID, PRINT_SPOOLER_PACKAGE_NAME))
|
||||
.contains(PM_CLEAR_SUCCESS_OUTPUT));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected PrinterDiscoverySessionCallbacks createMockPrinterDiscoverySessionCallbacks(
|
||||
Answer<Void> onStartPrinterDiscovery, Answer<Void> onStopPrinterDiscovery,
|
||||
Answer<Void> onValidatePrinters, Answer<Void> onStartPrinterStateTracking,
|
||||
Answer<Void> onRequestCustomPrinterIcon, Answer<Void> onStopPrinterStateTracking,
|
||||
Answer<Void> onDestroy) {
|
||||
PrinterDiscoverySessionCallbacks callbacks = mock(PrinterDiscoverySessionCallbacks.class);
|
||||
|
||||
doCallRealMethod().when(callbacks).setSession(any(StubbablePrinterDiscoverySession.class));
|
||||
when(callbacks.getSession()).thenCallRealMethod();
|
||||
|
||||
if (onStartPrinterDiscovery != null) {
|
||||
doAnswer(onStartPrinterDiscovery).when(callbacks).onStartPrinterDiscovery(
|
||||
any(List.class));
|
||||
}
|
||||
if (onStopPrinterDiscovery != null) {
|
||||
doAnswer(onStopPrinterDiscovery).when(callbacks).onStopPrinterDiscovery();
|
||||
}
|
||||
if (onValidatePrinters != null) {
|
||||
doAnswer(onValidatePrinters).when(callbacks).onValidatePrinters(
|
||||
any(List.class));
|
||||
}
|
||||
if (onStartPrinterStateTracking != null) {
|
||||
doAnswer(onStartPrinterStateTracking).when(callbacks).onStartPrinterStateTracking(
|
||||
any(PrinterId.class));
|
||||
}
|
||||
if (onRequestCustomPrinterIcon != null) {
|
||||
doAnswer(onRequestCustomPrinterIcon).when(callbacks).onRequestCustomPrinterIcon(
|
||||
any(PrinterId.class), any(CustomPrinterIconCallback.class));
|
||||
}
|
||||
if (onStopPrinterStateTracking != null) {
|
||||
doAnswer(onStopPrinterStateTracking).when(callbacks).onStopPrinterStateTracking(
|
||||
any(PrinterId.class));
|
||||
}
|
||||
if (onDestroy != null) {
|
||||
doAnswer(onDestroy).when(callbacks).onDestroy();
|
||||
}
|
||||
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
protected PrintServiceCallbacks createMockPrintServiceCallbacks(
|
||||
Answer<PrinterDiscoverySessionCallbacks> onCreatePrinterDiscoverySessionCallbacks,
|
||||
Answer<Void> onPrintJobQueued, Answer<Void> onRequestCancelPrintJob) {
|
||||
final PrintServiceCallbacks service = mock(PrintServiceCallbacks.class);
|
||||
|
||||
doCallRealMethod().when(service).setService(any(PrintService.class));
|
||||
when(service.getService()).thenCallRealMethod();
|
||||
|
||||
if (onCreatePrinterDiscoverySessionCallbacks != null) {
|
||||
doAnswer(onCreatePrinterDiscoverySessionCallbacks).when(service)
|
||||
.onCreatePrinterDiscoverySessionCallbacks();
|
||||
}
|
||||
if (onPrintJobQueued != null) {
|
||||
doAnswer(onPrintJobQueued).when(service).onPrintJobQueued(any(PrintJob.class));
|
||||
}
|
||||
if (onRequestCancelPrintJob != null) {
|
||||
doAnswer(onRequestCancelPrintJob).when(service).onRequestCancelPrintJob(
|
||||
any(PrintJob.class));
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
protected final class CallCounter {
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private int mCallCount;
|
||||
|
||||
public void call() {
|
||||
synchronized (mLock) {
|
||||
mCallCount++;
|
||||
mLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public int getCallCount() {
|
||||
synchronized (mLock) {
|
||||
return mCallCount;
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForCount(int count, long timeoutMillis) throws TimeoutException {
|
||||
synchronized (mLock) {
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
while (mCallCount < count) {
|
||||
try {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
final long remainingTimeMillis = timeoutMillis - elapsedTimeMillis;
|
||||
if (remainingTimeMillis <= 0) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
mLock.wait(timeoutMillis);
|
||||
} catch (InterruptedException ie) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean supportsPrinting() {
|
||||
return getInstrumentation().getContext().getPackageManager()
|
||||
.hasSystemFeature(PackageManager.FEATURE_PRINTING);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,669 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Process;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.print.IPrintDocumentAdapter;
|
||||
import android.print.IPrintJobStateChangeListener;
|
||||
import android.print.IPrintManager;
|
||||
import android.print.IPrinterDiscoveryObserver;
|
||||
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.PrintJob;
|
||||
import android.print.PrintJobId;
|
||||
import android.print.PrintJobInfo;
|
||||
import android.print.PrintManager;
|
||||
import android.print.PrinterCapabilitiesInfo;
|
||||
import android.print.PrinterDiscoverySession;
|
||||
import android.print.PrinterId;
|
||||
import android.print.PrinterInfo;
|
||||
import android.printservice.PrintServiceInfo;
|
||||
|
||||
import android.print.mockservice.MockPrintService;
|
||||
import android.print.mockservice.PrintServiceCallbacks;
|
||||
import android.print.mockservice.PrinterDiscoverySessionCallbacks;
|
||||
import android.print.mockservice.StubbablePrinterDiscoverySession;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* tests feeding all possible parameters to the IPrintManager Binder.
|
||||
*/
|
||||
public class IPrintManagerParametersTest extends BasePrintTest {
|
||||
|
||||
private final int BAD_APP_ID = 0xffffffff;
|
||||
|
||||
private final int mAppId;
|
||||
private final int mUserId;
|
||||
private final PrintJobId mBadPrintJobId;
|
||||
|
||||
private PrintJob mGoodPrintJob;
|
||||
private PrinterId mBadPrinterId;
|
||||
private PrinterId mGoodPrinterId;
|
||||
private ComponentName mGoodComponentName;
|
||||
private ComponentName mBadComponentName;
|
||||
|
||||
private IPrintManager mIPrintManager;
|
||||
|
||||
/**
|
||||
* Create a new IPrintManagerParametersTest and setup basic fields.
|
||||
*/
|
||||
public IPrintManagerParametersTest() {
|
||||
super();
|
||||
|
||||
mAppId = UserHandle.getAppId(Process.myUid());
|
||||
mUserId = UserHandle.myUserId();
|
||||
mBadPrintJobId = new PrintJobId();
|
||||
mBadComponentName = new ComponentName("bad", "bad");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a mock PrintDocumentAdapter.
|
||||
*
|
||||
* @return The adapter
|
||||
*/
|
||||
private @NonNull PrintDocumentAdapter createMockAdapter() {
|
||||
return new PrintDocumentAdapter() {
|
||||
@Override
|
||||
public void onStart() {
|
||||
onStartCalled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
|
||||
CancellationSignal cancellationSignal, LayoutResultCallback callback,
|
||||
Bundle extras) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
|
||||
CancellationSignal cancellationSignal, WriteResultCallback callback) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create mock print service callbacks.
|
||||
*
|
||||
* @return the callbacks
|
||||
*/
|
||||
private PrintServiceCallbacks createMockCallbacks() {
|
||||
return createMockPrintServiceCallbacks(
|
||||
new Answer<PrinterDiscoverySessionCallbacks>() {
|
||||
@Override
|
||||
public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
|
||||
return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) {
|
||||
// Get the session.
|
||||
StubbablePrinterDiscoverySession session =
|
||||
((PrinterDiscoverySessionCallbacks) invocation
|
||||
.getMock()).getSession();
|
||||
|
||||
if (session.getPrinters().isEmpty()) {
|
||||
final String PRINTER_NAME = "good printer";
|
||||
List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
|
||||
|
||||
// Add the printer.
|
||||
mGoodPrinterId = session.getService()
|
||||
.generatePrinterId(PRINTER_NAME);
|
||||
|
||||
PrinterCapabilitiesInfo capabilities =
|
||||
new PrinterCapabilitiesInfo.Builder(mGoodPrinterId)
|
||||
.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();
|
||||
|
||||
PrinterInfo printer = new PrinterInfo.Builder(
|
||||
mGoodPrinterId,
|
||||
PRINTER_NAME,
|
||||
PrinterInfo.STATUS_IDLE)
|
||||
.setCapabilities(capabilities)
|
||||
.build();
|
||||
printers.add(printer);
|
||||
|
||||
session.addPrinters(printers);
|
||||
}
|
||||
onPrinterDiscoverySessionStartCalled();
|
||||
return null;
|
||||
}
|
||||
}, null, null, null, null, null, null);
|
||||
}
|
||||
},
|
||||
null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a IPrintJobStateChangeListener object.
|
||||
*
|
||||
* @return the object
|
||||
* @throws Exception if the object could not be created.
|
||||
*/
|
||||
private IPrintJobStateChangeListener createMockIPrintJobStateChangeListener() throws Exception {
|
||||
return new PrintManager.PrintJobStateChangeListenerWrapper(null,
|
||||
new Handler(Looper.getMainLooper()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a IPrinterDiscoveryObserver object.
|
||||
*
|
||||
* @return the object
|
||||
* @throws Exception if the object could not be created.
|
||||
*/
|
||||
private IPrinterDiscoveryObserver createMockIPrinterDiscoveryObserver() throws Exception {
|
||||
return new PrinterDiscoverySession.PrinterDiscoveryObserver(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
MockPrintService.setCallbacks(createMockCallbacks());
|
||||
|
||||
mGoodComponentName = getActivity().getComponentName();
|
||||
|
||||
mGoodPrintJob = print(createMockAdapter(), null);
|
||||
|
||||
mIPrintManager = IPrintManager.Stub
|
||||
.asInterface(ServiceManager.getService(Context.PRINT_SERVICE));
|
||||
|
||||
// Generate dummy printerId which is a valid PrinterId object, but does not correspond to a
|
||||
// printer
|
||||
mBadPrinterId = new PrinterId(mGoodComponentName, "dummy printer");
|
||||
|
||||
// Wait for PrintActivity to be ready
|
||||
waitForStartAdapterCallbackCalled();
|
||||
|
||||
// Wait for printer discovery session to be ready
|
||||
waitForPrinterDiscoverySessionStartCallbackCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Runnable} that can throw and {@link Exception}
|
||||
*/
|
||||
private interface Invokable {
|
||||
/**
|
||||
* Execute the {@link Invokable}
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void run() throws Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the invokable throws an expectedException
|
||||
*
|
||||
* @param invokable The {@link Invokable} to run
|
||||
* @param expectedClass The {@link Exception} that is supposed to be thrown
|
||||
*/
|
||||
public void assertException(Invokable invokable, Class<? extends Exception> expectedClass)
|
||||
throws Exception {
|
||||
try {
|
||||
invokable.run();
|
||||
} catch (Exception e) {
|
||||
if (e.getClass().isAssignableFrom(expectedClass)) {
|
||||
return;
|
||||
} else {
|
||||
throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
|
||||
+ e.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
throw new AssertionError("No exception thrown");
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.getPrintJobInfo
|
||||
*/
|
||||
public void testGetPrintJobInfo() throws Exception {
|
||||
assertEquals(mGoodPrintJob.getId(), mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(),
|
||||
mAppId, mUserId).getId());
|
||||
assertEquals(null, mIPrintManager.getPrintJobInfo(mBadPrintJobId, mAppId, mUserId));
|
||||
assertEquals(null, mIPrintManager.getPrintJobInfo(null, mAppId, mUserId));
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.getPrintJobInfo(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
|
||||
}
|
||||
}, SecurityException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.getPrintJobInfos
|
||||
*/
|
||||
public void testGetPrintJobInfos() throws Exception {
|
||||
List<PrintJobInfo> infos = mIPrintManager.getPrintJobInfos(mAppId, mUserId);
|
||||
|
||||
boolean foundPrintJob = false;
|
||||
for (PrintJobInfo info : infos) {
|
||||
if (info.getId().equals(mGoodPrintJob.getId())) {
|
||||
assertEquals(PrintJobInfo.STATE_CREATED, info.getState());
|
||||
foundPrintJob = true;
|
||||
}
|
||||
}
|
||||
assertTrue(foundPrintJob);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.getPrintJobInfos(BAD_APP_ID, mUserId);
|
||||
}
|
||||
}, SecurityException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.print
|
||||
*/
|
||||
public void testPrint() throws Exception {
|
||||
final String name = "dummy print job";
|
||||
|
||||
final IPrintDocumentAdapter adapter = new PrintManager
|
||||
.PrintDocumentAdapterDelegate(getActivity(), createMockAdapter());
|
||||
|
||||
// Valid parameters are tested in setUp()
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.print(null, adapter, null, mGoodComponentName.getPackageName(),
|
||||
mAppId, mUserId);
|
||||
}
|
||||
}, IllegalArgumentException.class);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.print(name, null, null, mGoodComponentName.getPackageName(),
|
||||
mAppId, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.print(name, adapter, null, null, mAppId, mUserId);
|
||||
}
|
||||
}, IllegalArgumentException.class);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.print(name, adapter, null, mBadComponentName.getPackageName(),
|
||||
mAppId, mUserId);
|
||||
}
|
||||
}, IllegalArgumentException.class);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.print(name, adapter, null, mGoodComponentName.getPackageName(),
|
||||
BAD_APP_ID, mUserId);
|
||||
}
|
||||
}, SecurityException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.cancelPrintJob
|
||||
*/
|
||||
public void testCancelPrintJob() throws Exception {
|
||||
// Invalid print jobs IDs do not produce an exception
|
||||
mIPrintManager.cancelPrintJob(mBadPrintJobId, mAppId, mUserId);
|
||||
mIPrintManager.cancelPrintJob(null, mAppId, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
|
||||
}
|
||||
}, SecurityException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
|
||||
// Must be last as otherwise mGoodPrintJob will not be good anymore
|
||||
mIPrintManager.cancelPrintJob(mGoodPrintJob.getId(), mAppId, mUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.restartPrintJob
|
||||
*/
|
||||
public void testRestartPrintJob() throws Exception {
|
||||
mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), mAppId, mUserId);
|
||||
|
||||
// Invalid print jobs IDs do not produce an exception
|
||||
mIPrintManager.restartPrintJob(mBadPrintJobId, mAppId, mUserId);
|
||||
mIPrintManager.restartPrintJob(null, mAppId, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.restartPrintJob(mGoodPrintJob.getId(), BAD_APP_ID, mUserId);
|
||||
}
|
||||
}, SecurityException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.addPrintJobStateChangeListener
|
||||
*/
|
||||
public void testAddPrintJobStateChangeListener() throws Exception {
|
||||
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
|
||||
|
||||
mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.addPrintJobStateChangeListener(null, mAppId, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.addPrintJobStateChangeListener(listener, BAD_APP_ID, mUserId);
|
||||
}
|
||||
}, SecurityException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.removePrintJobStateChangeListener
|
||||
*/
|
||||
public void testRemovePrintJobStateChangeListener() throws Exception {
|
||||
final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
|
||||
|
||||
mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
|
||||
mIPrintManager.removePrintJobStateChangeListener(listener, mUserId);
|
||||
|
||||
// Removing unknown listeners is a no-op
|
||||
mIPrintManager.removePrintJobStateChangeListener(listener, mUserId);
|
||||
|
||||
mIPrintManager.addPrintJobStateChangeListener(listener, mAppId, mUserId);
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.removePrintJobStateChangeListener(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.getInstalledPrintServices
|
||||
*/
|
||||
public void testGetInstalledPrintServices() throws Exception {
|
||||
List<PrintServiceInfo> printServices = mIPrintManager.getInstalledPrintServices(mUserId);
|
||||
assertTrue(printServices.size() >= 2);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.getEnabledPrintServices
|
||||
*/
|
||||
public void testGetEnabledPrintServices() throws Exception {
|
||||
List<PrintServiceInfo> printServices = mIPrintManager.getEnabledPrintServices(mUserId);
|
||||
assertTrue(printServices.size() >= 2);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.createPrinterDiscoverySession
|
||||
*/
|
||||
public void testCreatePrinterDiscoverySession() throws Exception {
|
||||
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
|
||||
|
||||
mIPrintManager.createPrinterDiscoverySession(listener, mUserId);
|
||||
|
||||
try {
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.createPrinterDiscoverySession(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
} finally {
|
||||
// Remove discovery session so that the next test create a new one. Usually a leaked
|
||||
// session is removed on the next call from the print service. But in this case we want
|
||||
// to force a new call to onPrinterDiscoverySessionStart in the next test.
|
||||
mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.startPrinterDiscovery
|
||||
*/
|
||||
public void testStartPrinterDiscovery() throws Exception {
|
||||
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
|
||||
final List<PrinterId> goodPrinters = new ArrayList<>();
|
||||
goodPrinters.add(mGoodPrinterId);
|
||||
|
||||
final List<PrinterId> badPrinters = new ArrayList<>();
|
||||
badPrinters.add(mBadPrinterId);
|
||||
|
||||
final List<PrinterId> emptyPrinters = new ArrayList<>();
|
||||
|
||||
final List<PrinterId> nullPrinters = new ArrayList<>();
|
||||
nullPrinters.add(null);
|
||||
|
||||
mIPrintManager.startPrinterDiscovery(listener, goodPrinters, mUserId);
|
||||
|
||||
// Bad or no printers do no cause exceptions
|
||||
mIPrintManager.startPrinterDiscovery(listener, badPrinters, mUserId);
|
||||
mIPrintManager.startPrinterDiscovery(listener, emptyPrinters, mUserId);
|
||||
mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.startPrinterDiscovery(listener, nullPrinters, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.startPrinterDiscovery(null, goodPrinters, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.stopPrinterDiscovery
|
||||
*/
|
||||
public void testStopPrinterDiscovery() throws Exception {
|
||||
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
|
||||
|
||||
mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
|
||||
mIPrintManager.stopPrinterDiscovery(listener, mUserId);
|
||||
|
||||
// Stopping an already stopped session is a no-op
|
||||
mIPrintManager.stopPrinterDiscovery(listener, mUserId);
|
||||
|
||||
mIPrintManager.startPrinterDiscovery(listener, null, mUserId);
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.stopPrinterDiscovery(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.validatePrinters
|
||||
*/
|
||||
public void testValidatePrinters() throws Exception {
|
||||
final List<PrinterId> goodPrinters = new ArrayList<>();
|
||||
goodPrinters.add(mGoodPrinterId);
|
||||
|
||||
final List<PrinterId> badPrinters = new ArrayList<>();
|
||||
badPrinters.add(mBadPrinterId);
|
||||
|
||||
final List<PrinterId> emptyPrinters = new ArrayList<>();
|
||||
|
||||
final List<PrinterId> nullPrinters = new ArrayList<>();
|
||||
nullPrinters.add(null);
|
||||
|
||||
mIPrintManager.validatePrinters(goodPrinters, mUserId);
|
||||
|
||||
// Bad or empty list of printers do no cause exceptions
|
||||
mIPrintManager.validatePrinters(badPrinters, mUserId);
|
||||
mIPrintManager.validatePrinters(emptyPrinters, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.validatePrinters(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.validatePrinters(nullPrinters, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.startPrinterStateTracking
|
||||
*/
|
||||
public void testStartPrinterStateTracking() throws Exception {
|
||||
mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
|
||||
|
||||
// Bad printers do no cause exceptions
|
||||
mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.startPrinterStateTracking(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.getCustomPrinterIcon
|
||||
*/
|
||||
public void testGetCustomPrinterIcon() throws Exception {
|
||||
mIPrintManager.getCustomPrinterIcon(mGoodPrinterId, mUserId);
|
||||
|
||||
// Bad printers do no cause exceptions
|
||||
mIPrintManager.getCustomPrinterIcon(mBadPrinterId, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.getCustomPrinterIcon(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.stopPrinterStateTracking
|
||||
*/
|
||||
public void testStopPrinterStateTracking() throws Exception {
|
||||
mIPrintManager.startPrinterStateTracking(mGoodPrinterId, mUserId);
|
||||
mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
|
||||
|
||||
// Stop to track a non-tracked printer is a no-op
|
||||
mIPrintManager.stopPrinterStateTracking(mGoodPrinterId, mUserId);
|
||||
|
||||
// Bad printers do no cause exceptions
|
||||
mIPrintManager.startPrinterStateTracking(mBadPrinterId, mUserId);
|
||||
mIPrintManager.stopPrinterStateTracking(mBadPrinterId, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.stopPrinterStateTracking(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
|
||||
/**
|
||||
* test IPrintManager.destroyPrinterDiscoverySession
|
||||
*/
|
||||
public void testDestroyPrinterDiscoverySession() throws Exception {
|
||||
final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
|
||||
|
||||
mIPrintManager.createPrinterDiscoverySession(listener, mUserId);
|
||||
mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
|
||||
|
||||
// Destroying already destroyed session is a no-op
|
||||
mIPrintManager.destroyPrinterDiscoverySession(listener, mUserId);
|
||||
|
||||
assertException(new Invokable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
mIPrintManager.destroyPrinterDiscoverySession(null, mUserId);
|
||||
}
|
||||
}, NullPointerException.class);
|
||||
|
||||
// Cannot test bad user Id as these tests are allowed to call across users
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class PrintTestActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
||||
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
|
||||
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.mockservice;
|
||||
|
||||
public class MockPrintService extends StubbablePrintService {
|
||||
|
||||
private static final Object sLock = new Object();
|
||||
|
||||
private static PrintServiceCallbacks sCallbacks;
|
||||
|
||||
public static void setCallbacks(PrintServiceCallbacks callbacks) {
|
||||
synchronized (sLock) {
|
||||
sCallbacks = callbacks;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintServiceCallbacks getCallbacks() {
|
||||
synchronized (sLock) {
|
||||
if (sCallbacks != null) {
|
||||
sCallbacks.setService(this);
|
||||
}
|
||||
return sCallbacks;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.mockservice;
|
||||
|
||||
import android.printservice.PrintJob;
|
||||
import android.printservice.PrintService;
|
||||
|
||||
public abstract class PrintServiceCallbacks {
|
||||
|
||||
private PrintService mService;
|
||||
|
||||
public PrintService getService() {
|
||||
return mService;
|
||||
}
|
||||
|
||||
public void setService(PrintService service) {
|
||||
mService = service;
|
||||
}
|
||||
|
||||
public abstract PrinterDiscoverySessionCallbacks onCreatePrinterDiscoverySessionCallbacks();
|
||||
|
||||
public abstract void onRequestCancelPrintJob(PrintJob printJob);
|
||||
|
||||
public abstract void onPrintJobQueued(PrintJob printJob);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.mockservice;
|
||||
|
||||
import android.print.PrinterId;
|
||||
import android.printservice.CustomPrinterIconCallback;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class PrinterDiscoverySessionCallbacks {
|
||||
|
||||
private StubbablePrinterDiscoverySession mSession;
|
||||
|
||||
public void setSession(StubbablePrinterDiscoverySession session) {
|
||||
mSession = session;
|
||||
}
|
||||
|
||||
public StubbablePrinterDiscoverySession getSession() {
|
||||
return mSession;
|
||||
}
|
||||
|
||||
public abstract void onStartPrinterDiscovery(List<PrinterId> priorityList);
|
||||
|
||||
public abstract void onStopPrinterDiscovery();
|
||||
|
||||
public abstract void onValidatePrinters(List<PrinterId> printerIds);
|
||||
|
||||
public abstract void onStartPrinterStateTracking(PrinterId printerId);
|
||||
|
||||
public abstract void onRequestCustomPrinterIcon(PrinterId printerId,
|
||||
CustomPrinterIconCallback callback);
|
||||
|
||||
public abstract void onStopPrinterStateTracking(PrinterId printerId);
|
||||
|
||||
public abstract void onDestroy();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.mockservice;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class SettingsActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.mockservice;
|
||||
|
||||
import android.printservice.PrintJob;
|
||||
import android.printservice.PrintService;
|
||||
import android.printservice.PrinterDiscoverySession;
|
||||
|
||||
public abstract class StubbablePrintService extends PrintService {
|
||||
|
||||
@Override
|
||||
public PrinterDiscoverySession onCreatePrinterDiscoverySession() {
|
||||
PrintServiceCallbacks callbacks = getCallbacks();
|
||||
if (callbacks != null) {
|
||||
return new StubbablePrinterDiscoverySession(this,
|
||||
getCallbacks().onCreatePrinterDiscoverySessionCallbacks());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestCancelPrintJob(PrintJob printJob) {
|
||||
PrintServiceCallbacks callbacks = getCallbacks();
|
||||
if (callbacks != null) {
|
||||
callbacks.onRequestCancelPrintJob(printJob);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrintJobQueued(PrintJob printJob) {
|
||||
PrintServiceCallbacks callbacks = getCallbacks();
|
||||
if (callbacks != null) {
|
||||
callbacks.onPrintJobQueued(printJob);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract PrintServiceCallbacks getCallbacks();
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.mockservice;
|
||||
|
||||
import android.print.PrinterId;
|
||||
import android.printservice.CustomPrinterIconCallback;
|
||||
import android.printservice.PrintService;
|
||||
import android.printservice.PrinterDiscoverySession;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StubbablePrinterDiscoverySession extends PrinterDiscoverySession {
|
||||
private final PrintService mService;
|
||||
private final PrinterDiscoverySessionCallbacks mCallbacks;
|
||||
|
||||
public StubbablePrinterDiscoverySession(PrintService service,
|
||||
PrinterDiscoverySessionCallbacks callbacks) {
|
||||
mService = service;
|
||||
mCallbacks = callbacks;
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.setSession(this);
|
||||
}
|
||||
}
|
||||
|
||||
public PrintService getService() {
|
||||
return mService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartPrinterDiscovery(List<PrinterId> priorityList) {
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onStartPrinterDiscovery(priorityList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopPrinterDiscovery() {
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onStopPrinterDiscovery();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValidatePrinters(List<PrinterId> printerIds) {
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onValidatePrinters(printerIds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartPrinterStateTracking(PrinterId printerId) {
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onStartPrinterStateTracking(printerId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestCustomPrinterIcon(PrinterId printerId,
|
||||
CustomPrinterIconCallback callback) {
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onRequestCustomPrinterIcon(printerId, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopPrinterStateTracking(PrinterId printerId) {
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onStopPrinterStateTracking(printerId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mCallbacks != null) {
|
||||
mCallbacks.onDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.printspooler.ui;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
@@ -452,7 +453,7 @@ public final class FusedPrintersProvider extends Loader<List<PrinterInfo>>
|
||||
return mPersistenceManager.mReadHistoryCompleted;
|
||||
}
|
||||
|
||||
public void setTrackedPrinter(PrinterId printerId) {
|
||||
public void setTrackedPrinter(@Nullable PrinterId printerId) {
|
||||
if (isStarted() && mDiscoverySession != null
|
||||
&& mDiscoverySession.isPrinterDiscoveryStarted()) {
|
||||
if (mTrackedPrinter != null) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.printspooler.ui;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.LoaderManager.LoaderCallbacks;
|
||||
import android.content.Loader;
|
||||
@@ -89,7 +90,7 @@ public class PrinterRegistry {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setTrackedPrinter(PrinterId printerId) {
|
||||
public void setTrackedPrinter(@Nullable PrinterId printerId) {
|
||||
FusedPrintersProvider provider = getPrinterProvider();
|
||||
if (provider != null) {
|
||||
provider.setTrackedPrinter(printerId);
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.GET_SERVICES;
|
||||
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.content.ComponentName;
|
||||
@@ -47,11 +48,11 @@ import android.print.PrintJobInfo;
|
||||
import android.print.PrinterId;
|
||||
import android.printservice.PrintServiceInfo;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.SystemService;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -108,6 +109,10 @@ public final class PrintManagerService extends SystemService {
|
||||
@Override
|
||||
public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
|
||||
PrintAttributes attributes, String packageName, int appId, int userId) {
|
||||
printJobName = Preconditions.checkStringNotEmpty(printJobName);
|
||||
adapter = Preconditions.checkNotNull(adapter);
|
||||
packageName = Preconditions.checkStringNotEmpty(packageName);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final int resolvedAppId;
|
||||
final UserState userState;
|
||||
@@ -153,6 +158,10 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
|
||||
if (printJobId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final int resolvedAppId;
|
||||
final UserState userState;
|
||||
@@ -174,6 +183,8 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public Icon getCustomPrinterIcon(PrinterId printerId, int userId) {
|
||||
printerId = Preconditions.checkNotNull(printerId);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -193,6 +204,10 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
|
||||
if (printJobId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final int resolvedAppId;
|
||||
final UserState userState;
|
||||
@@ -214,6 +229,10 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
|
||||
if (printJobId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final int resolvedAppId;
|
||||
final UserState userState;
|
||||
@@ -279,6 +298,8 @@ public final class PrintManagerService extends SystemService {
|
||||
@Override
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
|
||||
int userId) {
|
||||
observer = Preconditions.checkNotNull(observer);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -299,6 +320,8 @@ public final class PrintManagerService extends SystemService {
|
||||
@Override
|
||||
public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
|
||||
int userId) {
|
||||
observer = Preconditions.checkNotNull(observer);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -319,6 +342,12 @@ public final class PrintManagerService extends SystemService {
|
||||
@Override
|
||||
public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
|
||||
List<PrinterId> priorityList, int userId) {
|
||||
observer = Preconditions.checkNotNull(observer);
|
||||
if (priorityList != null) {
|
||||
priorityList = Preconditions.checkCollectionElementsNotNull(priorityList,
|
||||
"PrinterId");
|
||||
}
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -338,6 +367,8 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) {
|
||||
observer = Preconditions.checkNotNull(observer);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -357,6 +388,8 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void validatePrinters(List<PrinterId> printerIds, int userId) {
|
||||
printerIds = Preconditions.checkCollectionElementsNotNull(printerIds, "PrinterId");
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -376,6 +409,8 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void startPrinterStateTracking(PrinterId printerId, int userId) {
|
||||
printerId = Preconditions.checkNotNull(printerId);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -395,6 +430,8 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void stopPrinterStateTracking(PrinterId printerId, int userId) {
|
||||
printerId = Preconditions.checkNotNull(printerId);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -415,6 +452,8 @@ public final class PrintManagerService extends SystemService {
|
||||
@Override
|
||||
public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
|
||||
int appId, int userId) throws RemoteException {
|
||||
listener = Preconditions.checkNotNull(listener);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final int resolvedAppId;
|
||||
final UserState userState;
|
||||
@@ -437,6 +476,8 @@ public final class PrintManagerService extends SystemService {
|
||||
@Override
|
||||
public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener,
|
||||
int userId) {
|
||||
listener = Preconditions.checkNotNull(listener);
|
||||
|
||||
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
@@ -456,6 +497,9 @@ public final class PrintManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
fd = Preconditions.checkNotNull(fd);
|
||||
pw = Preconditions.checkNotNull(pw);
|
||||
|
||||
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
pw.println("Permission Denial: can't dump PrintManager from from pid="
|
||||
@@ -707,10 +751,8 @@ public final class PrintManagerService extends SystemService {
|
||||
return userId;
|
||||
}
|
||||
|
||||
private String resolveCallingPackageNameEnforcingSecurity(String packageName) {
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
return null;
|
||||
}
|
||||
private @NonNull String resolveCallingPackageNameEnforcingSecurity(
|
||||
@NonNull String packageName) {
|
||||
String[] packages = mContext.getPackageManager().getPackagesForUid(
|
||||
Binder.getCallingUid());
|
||||
final int packageCount = packages.length;
|
||||
@@ -719,7 +761,7 @@ public final class PrintManagerService extends SystemService {
|
||||
return packageName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
throw new IllegalArgumentException("packageName has to belong to the caller");
|
||||
}
|
||||
|
||||
private int getCurrentUserId () {
|
||||
|
||||
@@ -409,7 +409,7 @@ final class RemotePrintService implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrinterStateTracking(PrinterId printerId) {
|
||||
public void startPrinterStateTracking(@NonNull PrinterId printerId) {
|
||||
mHandler.obtainMessage(MyHandler.MSG_START_PRINTER_STATE_TRACKING,
|
||||
printerId).sendToTarget();
|
||||
}
|
||||
@@ -420,7 +420,7 @@ final class RemotePrintService implements DeathRecipient {
|
||||
* @param printerId the id of the printer the icon should be loaded for
|
||||
* @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
|
||||
*/
|
||||
public void requestCustomPrinterIcon(PrinterId printerId) {
|
||||
public void requestCustomPrinterIcon(@NonNull PrinterId printerId) {
|
||||
try {
|
||||
if (isBound()) {
|
||||
mPrintService.requestCustomPrinterIcon(printerId);
|
||||
@@ -430,7 +430,7 @@ final class RemotePrintService implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStartPrinterStateTracking(final PrinterId printerId) {
|
||||
private void handleStartPrinterStateTracking(final @NonNull PrinterId printerId) {
|
||||
throwIfDestroyed();
|
||||
// Take a note we are tracking the printer.
|
||||
if (mTrackedPrinterList == null) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.GET_META_DATA;
|
||||
import static android.content.pm.PackageManager.GET_SERVICES;
|
||||
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
@@ -176,8 +177,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
|
||||
PrintAttributes attributes, String packageName, int appId) {
|
||||
public Bundle print(@NonNull String printJobName, @NonNull IPrintDocumentAdapter adapter,
|
||||
@Nullable PrintAttributes attributes, @NonNull String packageName, int appId) {
|
||||
// Create print job place holder.
|
||||
final PrintJobInfo printJob = new PrintJobInfo();
|
||||
printJob.setId(new PrintJobId());
|
||||
@@ -267,7 +268,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
return new ArrayList<PrintJobInfo>(result.values());
|
||||
}
|
||||
|
||||
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
|
||||
public PrintJobInfo getPrintJobInfo(@NonNull PrintJobId printJobId, int appId) {
|
||||
PrintJobInfo printJob = mPrintJobForAppCache.getPrintJob(printJobId, appId);
|
||||
if (printJob == null) {
|
||||
printJob = mSpooler.getPrintJobInfo(printJobId, appId);
|
||||
@@ -290,7 +291,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
* not yet available
|
||||
* @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
|
||||
*/
|
||||
public Icon getCustomPrinterIcon(PrinterId printerId) {
|
||||
public @Nullable Icon getCustomPrinterIcon(@NonNull PrinterId printerId) {
|
||||
Icon icon = mSpooler.getCustomPrinterIcon(printerId);
|
||||
|
||||
if (icon == null) {
|
||||
@@ -303,7 +304,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void cancelPrintJob(PrintJobId printJobId, int appId) {
|
||||
public void cancelPrintJob(@NonNull PrintJobId printJobId, int appId) {
|
||||
PrintJobInfo printJobInfo = mSpooler.getPrintJobInfo(printJobId, appId);
|
||||
if (printJobInfo == null) {
|
||||
return;
|
||||
@@ -313,15 +314,19 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
mSpooler.setPrintJobCancelling(printJobId, true);
|
||||
|
||||
if (printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
|
||||
ComponentName printServiceName = printJobInfo.getPrinterId().getServiceName();
|
||||
RemotePrintService printService = null;
|
||||
synchronized (mLock) {
|
||||
printService = mActiveServices.get(printServiceName);
|
||||
PrinterId printerId = printJobInfo.getPrinterId();
|
||||
|
||||
if (printerId != null) {
|
||||
ComponentName printServiceName = printerId.getServiceName();
|
||||
RemotePrintService printService = null;
|
||||
synchronized (mLock) {
|
||||
printService = mActiveServices.get(printServiceName);
|
||||
}
|
||||
if (printService == null) {
|
||||
return;
|
||||
}
|
||||
printService.onRequestCancelPrintJob(printJobInfo);
|
||||
}
|
||||
if (printService == null) {
|
||||
return;
|
||||
}
|
||||
printService.onRequestCancelPrintJob(printJobInfo);
|
||||
} else {
|
||||
// If the print job is failed we do not need cooperation
|
||||
// from the print service.
|
||||
@@ -329,7 +334,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void restartPrintJob(PrintJobId printJobId, int appId) {
|
||||
public void restartPrintJob(@NonNull PrintJobId printJobId, int appId) {
|
||||
PrintJobInfo printJobInfo = getPrintJobInfo(printJobId, appId);
|
||||
if (printJobInfo == null || printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
|
||||
return;
|
||||
@@ -363,7 +368,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer) {
|
||||
public void createPrinterDiscoverySession(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
|
||||
@@ -386,7 +391,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer) {
|
||||
public void destroyPrinterDiscoverySession(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
synchronized (mLock) {
|
||||
// Already destroyed - nothing to do.
|
||||
if (mPrinterDiscoverySession == null) {
|
||||
@@ -397,8 +402,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
|
||||
List<PrinterId> printerIds) {
|
||||
public void startPrinterDiscovery(@NonNull IPrinterDiscoveryObserver observer,
|
||||
@Nullable List<PrinterId> printerIds) {
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
// No services - nothing to do.
|
||||
@@ -415,7 +420,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer) {
|
||||
public void stopPrinterDiscovery(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
// No services - nothing to do.
|
||||
@@ -431,7 +436,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void validatePrinters(List<PrinterId> printerIds) {
|
||||
public void validatePrinters(@NonNull List<PrinterId> printerIds) {
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
// No services - nothing to do.
|
||||
@@ -447,7 +452,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrinterStateTracking(PrinterId printerId) {
|
||||
public void startPrinterStateTracking(@NonNull PrinterId printerId) {
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
// No services - nothing to do.
|
||||
@@ -479,7 +484,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
|
||||
public void addPrintJobStateChangeListener(@NonNull IPrintJobStateChangeListener listener,
|
||||
int appId) throws RemoteException {
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
@@ -497,7 +502,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener) {
|
||||
public void removePrintJobStateChangeListener(@NonNull IPrintJobStateChangeListener listener) {
|
||||
synchronized (mLock) {
|
||||
throwIfDestroyedLocked();
|
||||
if (mPrintJobStateChangeListenerRecords == null) {
|
||||
@@ -613,7 +618,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
|
||||
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String prefix) {
|
||||
pw.append(prefix).append("user state ").append(String.valueOf(mUserId)).append(":");
|
||||
pw.println();
|
||||
|
||||
@@ -991,10 +996,10 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
|
||||
private abstract class PrintJobStateChangeListenerRecord implements DeathRecipient {
|
||||
final IPrintJobStateChangeListener listener;
|
||||
@NonNull final IPrintJobStateChangeListener listener;
|
||||
final int appId;
|
||||
|
||||
public PrintJobStateChangeListenerRecord(IPrintJobStateChangeListener listener,
|
||||
public PrintJobStateChangeListenerRecord(@NonNull IPrintJobStateChangeListener listener,
|
||||
int appId) throws RemoteException {
|
||||
this.listener = listener;
|
||||
this.appId = appId;
|
||||
@@ -1043,7 +1048,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
public void addObserverLocked(IPrinterDiscoveryObserver observer) {
|
||||
public void addObserverLocked(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
// Add the observer.
|
||||
mDiscoveryObservers.register(observer);
|
||||
|
||||
@@ -1058,7 +1063,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void removeObserverLocked(IPrinterDiscoveryObserver observer) {
|
||||
public void removeObserverLocked(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
// Remove the observer.
|
||||
mDiscoveryObservers.unregister(observer);
|
||||
// No one else observing - then kill it.
|
||||
@@ -1067,8 +1072,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public final void startPrinterDiscoveryLocked(IPrinterDiscoveryObserver observer,
|
||||
List<PrinterId> priorityList) {
|
||||
public final void startPrinterDiscoveryLocked(@NonNull IPrinterDiscoveryObserver observer,
|
||||
@Nullable List<PrinterId> priorityList) {
|
||||
if (mIsDestroyed) {
|
||||
Log.w(LOG_TAG, "Not starting dicovery - session destroyed");
|
||||
return;
|
||||
@@ -1101,7 +1106,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
public final void stopPrinterDiscoveryLocked(IPrinterDiscoveryObserver observer) {
|
||||
public final void stopPrinterDiscoveryLocked(@NonNull IPrinterDiscoveryObserver observer) {
|
||||
if (mIsDestroyed) {
|
||||
Log.w(LOG_TAG, "Not stopping dicovery - session destroyed");
|
||||
return;
|
||||
@@ -1121,7 +1126,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
public void validatePrintersLocked(List<PrinterId> printerIds) {
|
||||
public void validatePrintersLocked(@NonNull List<PrinterId> printerIds) {
|
||||
if (mIsDestroyed) {
|
||||
Log.w(LOG_TAG, "Not validating pritners - session destroyed");
|
||||
return;
|
||||
@@ -1135,13 +1140,15 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
ComponentName serviceName = null;
|
||||
while (iterator.hasNext()) {
|
||||
PrinterId printerId = iterator.next();
|
||||
if (updateList.isEmpty()) {
|
||||
updateList.add(printerId);
|
||||
serviceName = printerId.getServiceName();
|
||||
iterator.remove();
|
||||
} else if (printerId.getServiceName().equals(serviceName)) {
|
||||
updateList.add(printerId);
|
||||
iterator.remove();
|
||||
if (printerId != null) {
|
||||
if (updateList.isEmpty()) {
|
||||
updateList.add(printerId);
|
||||
serviceName = printerId.getServiceName();
|
||||
iterator.remove();
|
||||
} else if (printerId.getServiceName().equals(serviceName)) {
|
||||
updateList.add(printerId);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Schedule a notification of the service.
|
||||
@@ -1157,7 +1164,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public final void startPrinterStateTrackingLocked(PrinterId printerId) {
|
||||
public final void startPrinterStateTrackingLocked(@NonNull PrinterId printerId) {
|
||||
if (mIsDestroyed) {
|
||||
Log.w(LOG_TAG, "Not starting printer state tracking - session destroyed");
|
||||
return;
|
||||
@@ -1500,8 +1507,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||
service.validatePrinters(printerIds);
|
||||
}
|
||||
|
||||
private void handleStartPrinterStateTracking(RemotePrintService service,
|
||||
PrinterId printerId) {
|
||||
private void handleStartPrinterStateTracking(@NonNull RemotePrintService service,
|
||||
@NonNull PrinterId printerId) {
|
||||
service.startPrinterStateTracking(printerId);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user