19dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann/*
29dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Copyright (C) 2016 The Android Open Source Project
39dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
49dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Licensed under the Apache License, Version 2.0 (the "License");
59dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * you may not use this file except in compliance with the License.
69dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * You may obtain a copy of the License at
79dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
89dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *      http://www.apache.org/licenses/LICENSE-2.0
99dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann *
109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Unless required by applicable law or agreed to in writing, software
119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * distributed under the License is distributed on an "AS IS" BASIS,
129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * See the License for the specific language governing permissions and
149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * limitations under the License.
159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */
169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannpackage com.android.printservice.recommendation;
189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.annotation.IntRange;
209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.annotation.NonNull;
219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.annotation.StringRes;
229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport com.android.internal.util.Preconditions;
239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann/**
259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Wrapper for a {@link PrintServicePlugin}, isolating issues with the plugin as good as possible
269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * from the {@link RecommendationServiceImpl service}.
279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */
289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannclass RemotePrintServicePlugin implements PrintServicePlugin.PrinterDiscoveryCallback {
299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Lock for this object */
309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private final Object mLock = new Object();
319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** The name of the print service. */
339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public final @StringRes int name;
349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** If the print service if for more than a single vendor */
369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public final boolean recommendsMultiVendorService;
379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** The package name of the full print service */
399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public final @NonNull CharSequence packageName;
409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Wrapped plugin */
429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private final @NonNull PrintServicePlugin mPlugin;
439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** The number of printers discovered by the plugin */
459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private @IntRange(from = 0) int mNumPrinters;
469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** If the plugin is started by not yet stopped */
489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private boolean isRunning;
499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /** Listener for changes to {@link #mNumPrinters}. */
519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    private @NonNull OnChangedListener mListener;
529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Create a new remote for a {@link PrintServicePlugin plugin}.
559dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
569dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param plugin                       The plugin to be wrapped
579dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param listener                     The listener to be notified about changes in this plugin
589dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @param recommendsMultiVendorService If the plugin detects printers of more than a single
599dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *                                     vendor
609dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
619dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @throws PluginException If the plugin has issues while caching basic stub properties
629dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
639dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public RemotePrintServicePlugin(@NonNull PrintServicePlugin plugin,
649dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            @NonNull OnChangedListener listener, boolean recommendsMultiVendorService)
659dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throws PluginException {
669dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        mListener = listener;
679dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        mPlugin = plugin;
689dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        this.recommendsMultiVendorService = recommendsMultiVendorService;
699dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
709dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        // We handle any throwable to isolate our self from bugs in the plugin code.
719dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        // Cache simple properties to avoid having to deal with exceptions later in the code.
729dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        try {
739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            name = Preconditions.checkArgumentPositive(mPlugin.getName(), "name");
749dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            packageName = Preconditions.checkStringNotEmpty(mPlugin.getPackageName(),
759dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    "packageName");
769dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        } catch (Throwable e) {
779dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new PluginException(mPlugin, "Cannot cache simple properties ", e);
789dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
799dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
809dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        isRunning = false;
819dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
829dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Start the plugin. From now on there might be callbacks to the registered listener.
859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public void start()
879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throws PluginException {
889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        // We handle any throwable to isolate our self from bugs in the stub code
899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        try {
909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            synchronized (mLock) {
919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                isRunning = true;
929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mPlugin.start(this);
939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        } catch (Throwable e) {
959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new PluginException(mPlugin, "Cannot start", e);
969dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
999dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1009dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Stop the plugin. From this call on there will not be any more callbacks.
1019dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public void stop() throws PluginException {
1039dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        // We handle any throwable to isolate our self from bugs in the stub code
1049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        try {
1059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            synchronized (mLock) {
1069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mPlugin.stop();
1079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                isRunning = false;
1089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        } catch (Throwable e) {
1109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            throw new PluginException(mPlugin, "Cannot stop", e);
1119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Get the current number of printers reported by the stub.
1169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     *
1179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * @return The number of printers reported by the stub.
1189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public @IntRange(from = 0) int getNumPrinters() {
1209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        return mNumPrinters;
1219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    @Override
1249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public void onChanged(@IntRange(from = 0) int numDiscoveredPrinters) {
1259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        synchronized (mLock) {
1269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            Preconditions.checkState(isRunning);
1279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            mNumPrinters = Preconditions.checkArgumentNonnegative(numDiscoveredPrinters,
1299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                    "numDiscoveredPrinters");
1309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            if (mNumPrinters > 0) {
1329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann                mListener.onChanged();
1339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            }
1349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Listener to listen for changes to {@link #getNumPrinters}
1399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public interface OnChangedListener {
1419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        void onChanged();
1429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann
1449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    /**
1459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     * Exception thrown if the stub has any issues.
1469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann     */
1479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    public class PluginException extends Exception {
1489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        private PluginException(PrintServicePlugin plugin, String message, Throwable e) {
1499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann            super(plugin + ": " + message, e);
1509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann        }
1519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann    }
1529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann}
153