blob: 3cfb8655ed0c576adf2d972090b117871ce57fed [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.printservice.recommendation;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import com.android.printservice.recommendation.util.Preconditions;
import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
/**
* Wrapper for a {@link PrintServicePlugin}, isolating issues with the plugin as good as possible
* from the {@link RecommendationServiceImpl service}.
*/
class RemotePrintServicePlugin implements PrintServicePlugin.PrinterDiscoveryCallback {
/** Lock for this object */
private final Object mLock = new Object();
/** The name of the print service. */
public final @StringRes int name;
/** If the print service if for more than a single vendor */
public final boolean recommendsMultiVendorService;
/** The package name of the full print service */
public final @NonNull CharSequence packageName;
/** Wrapped plugin */
private final @NonNull PrintServicePlugin mPlugin;
/** The printers discovered by the plugin */
private @NonNull List<InetAddress> mPrinters;
/** If the plugin is started by not yet stopped */
private boolean isRunning;
/** Listener for changes to {@link #mPrinters}. */
private @NonNull OnChangedListener mListener;
/**
* Create a new remote for a {@link PrintServicePlugin plugin}.
*
* @param plugin The plugin to be wrapped
* @param listener The listener to be notified about changes in this plugin
* @param recommendsMultiVendorService If the plugin detects printers of more than a single
* vendor
*
* @throws PluginException If the plugin has issues while caching basic stub properties
*/
public RemotePrintServicePlugin(@NonNull PrintServicePlugin plugin,
@NonNull OnChangedListener listener, boolean recommendsMultiVendorService)
throws PluginException {
mListener = listener;
mPlugin = plugin;
mPrinters = Collections.emptyList();
this.recommendsMultiVendorService = recommendsMultiVendorService;
// We handle any throwable to isolate our self from bugs in the plugin code.
// Cache simple properties to avoid having to deal with exceptions later in the code.
try {
name = Preconditions.checkArgumentPositive(mPlugin.getName(), "name");
packageName = Preconditions.checkStringNotEmpty(mPlugin.getPackageName(),
"packageName");
} catch (Throwable e) {
throw new PluginException(mPlugin, "Cannot cache simple properties ", e);
}
isRunning = false;
}
/**
* Start the plugin. From now on there might be callbacks to the registered listener.
*/
public void start()
throws PluginException {
// We handle any throwable to isolate our self from bugs in the stub code
try {
synchronized (mLock) {
isRunning = true;
mPlugin.start(this);
}
} catch (Throwable e) {
throw new PluginException(mPlugin, "Cannot start", e);
}
}
/**
* Stop the plugin. From this call on there will not be any more callbacks.
*/
public void stop() throws PluginException {
// We handle any throwable to isolate our self from bugs in the stub code
try {
synchronized (mLock) {
mPlugin.stop();
isRunning = false;
}
} catch (Throwable e) {
throw new PluginException(mPlugin, "Cannot stop", e);
}
}
/**
* Get the current number of printers reported by the stub.
*
* @return The number of printers reported by the stub.
*/
public @NonNull List<InetAddress> getPrinters() {
return mPrinters;
}
@Override
public void onChanged(@Nullable List<InetAddress> discoveredPrinters) {
synchronized (mLock) {
Preconditions.checkState(isRunning);
if (discoveredPrinters == null) {
mPrinters = Collections.emptyList();
} else {
mPrinters = Preconditions.checkCollectionElementsNotNull(discoveredPrinters,
"discoveredPrinters");
}
mListener.onChanged();
}
}
/**
* Listener to listen for changes to {@link #getPrinters}
*/
public interface OnChangedListener {
void onChanged();
}
/**
* Exception thrown if the stub has any issues.
*/
public class PluginException extends Exception {
private PluginException(PrintServicePlugin plugin, String message, Throwable e) {
super(plugin + ": " + message, e);
}
}
}