Home | History | Annotate | Download | only in recommendation
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.printservice.recommendation;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.annotation.StringRes;
     22 
     23 import com.android.internal.util.Preconditions;
     24 
     25 import java.net.InetAddress;
     26 import java.util.Collections;
     27 import java.util.List;
     28 
     29 /**
     30  * Wrapper for a {@link PrintServicePlugin}, isolating issues with the plugin as good as possible
     31  * from the {@link RecommendationServiceImpl service}.
     32  */
     33 class RemotePrintServicePlugin implements PrintServicePlugin.PrinterDiscoveryCallback {
     34     /** Lock for this object */
     35     private final Object mLock = new Object();
     36 
     37     /** The name of the print service. */
     38     public final @StringRes int name;
     39 
     40     /** If the print service if for more than a single vendor */
     41     public final boolean recommendsMultiVendorService;
     42 
     43     /** The package name of the full print service */
     44     public final @NonNull CharSequence packageName;
     45 
     46     /** Wrapped plugin */
     47     private final @NonNull PrintServicePlugin mPlugin;
     48 
     49     /** The printers discovered by the plugin */
     50     private @NonNull List<InetAddress> mPrinters;
     51 
     52     /** If the plugin is started by not yet stopped */
     53     private boolean isRunning;
     54 
     55     /** Listener for changes to {@link #mPrinters}. */
     56     private @NonNull OnChangedListener mListener;
     57 
     58     /**
     59      * Create a new remote for a {@link PrintServicePlugin plugin}.
     60      *
     61      * @param plugin                       The plugin to be wrapped
     62      * @param listener                     The listener to be notified about changes in this plugin
     63      * @param recommendsMultiVendorService If the plugin detects printers of more than a single
     64      *                                     vendor
     65      *
     66      * @throws PluginException If the plugin has issues while caching basic stub properties
     67      */
     68     public RemotePrintServicePlugin(@NonNull PrintServicePlugin plugin,
     69             @NonNull OnChangedListener listener, boolean recommendsMultiVendorService)
     70             throws PluginException {
     71         mListener = listener;
     72         mPlugin = plugin;
     73         mPrinters = Collections.emptyList();
     74 
     75         this.recommendsMultiVendorService = recommendsMultiVendorService;
     76 
     77         // We handle any throwable to isolate our self from bugs in the plugin code.
     78         // Cache simple properties to avoid having to deal with exceptions later in the code.
     79         try {
     80             name = Preconditions.checkArgumentPositive(mPlugin.getName(), "name");
     81             packageName = Preconditions.checkStringNotEmpty(mPlugin.getPackageName(),
     82                     "packageName");
     83         } catch (Throwable e) {
     84             throw new PluginException(mPlugin, "Cannot cache simple properties ", e);
     85         }
     86 
     87         isRunning = false;
     88     }
     89 
     90     /**
     91      * Start the plugin. From now on there might be callbacks to the registered listener.
     92      */
     93     public void start()
     94             throws PluginException {
     95         // We handle any throwable to isolate our self from bugs in the stub code
     96         try {
     97             synchronized (mLock) {
     98                 isRunning = true;
     99                 mPlugin.start(this);
    100             }
    101         } catch (Throwable e) {
    102             throw new PluginException(mPlugin, "Cannot start", e);
    103         }
    104     }
    105 
    106     /**
    107      * Stop the plugin. From this call on there will not be any more callbacks.
    108      */
    109     public void stop() throws PluginException {
    110         // We handle any throwable to isolate our self from bugs in the stub code
    111         try {
    112             synchronized (mLock) {
    113                 mPlugin.stop();
    114                 isRunning = false;
    115             }
    116         } catch (Throwable e) {
    117             throw new PluginException(mPlugin, "Cannot stop", e);
    118         }
    119     }
    120 
    121     /**
    122      * Get the current number of printers reported by the stub.
    123      *
    124      * @return The number of printers reported by the stub.
    125      */
    126     public @NonNull List<InetAddress> getPrinters() {
    127         return mPrinters;
    128     }
    129 
    130     @Override
    131     public void onChanged(@Nullable List<InetAddress> discoveredPrinters) {
    132         synchronized (mLock) {
    133             Preconditions.checkState(isRunning);
    134 
    135             if (discoveredPrinters == null) {
    136                 mPrinters = Collections.emptyList();
    137             } else {
    138                 mPrinters = Preconditions.checkCollectionElementsNotNull(discoveredPrinters,
    139                         "discoveredPrinters");
    140             }
    141 
    142             mListener.onChanged();
    143         }
    144     }
    145 
    146     /**
    147      * Listener to listen for changes to {@link #getPrinters}
    148      */
    149     public interface OnChangedListener {
    150         void onChanged();
    151     }
    152 
    153     /**
    154      * Exception thrown if the stub has any issues.
    155      */
    156     public class PluginException extends Exception {
    157         private PluginException(PrintServicePlugin plugin, String message, Throwable e) {
    158             super(plugin + ": " + message, e);
    159         }
    160     }
    161 }
    162