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.IntRange; 20 import android.annotation.NonNull; 21 import android.annotation.StringRes; 22 import com.android.internal.util.Preconditions; 23 24 /** 25 * Wrapper for a {@link PrintServicePlugin}, isolating issues with the plugin as good as possible 26 * from the {@link RecommendationServiceImpl service}. 27 */ 28 class RemotePrintServicePlugin implements PrintServicePlugin.PrinterDiscoveryCallback { 29 /** Lock for this object */ 30 private final Object mLock = new Object(); 31 32 /** The name of the print service. */ 33 public final @StringRes int name; 34 35 /** If the print service if for more than a single vendor */ 36 public final boolean recommendsMultiVendorService; 37 38 /** The package name of the full print service */ 39 public final @NonNull CharSequence packageName; 40 41 /** Wrapped plugin */ 42 private final @NonNull PrintServicePlugin mPlugin; 43 44 /** The number of printers discovered by the plugin */ 45 private @IntRange(from = 0) int mNumPrinters; 46 47 /** If the plugin is started by not yet stopped */ 48 private boolean isRunning; 49 50 /** Listener for changes to {@link #mNumPrinters}. */ 51 private @NonNull OnChangedListener mListener; 52 53 /** 54 * Create a new remote for a {@link PrintServicePlugin plugin}. 55 * 56 * @param plugin The plugin to be wrapped 57 * @param listener The listener to be notified about changes in this plugin 58 * @param recommendsMultiVendorService If the plugin detects printers of more than a single 59 * vendor 60 * 61 * @throws PluginException If the plugin has issues while caching basic stub properties 62 */ RemotePrintServicePlugin(@onNull PrintServicePlugin plugin, @NonNull OnChangedListener listener, boolean recommendsMultiVendorService)63 public RemotePrintServicePlugin(@NonNull PrintServicePlugin plugin, 64 @NonNull OnChangedListener listener, boolean recommendsMultiVendorService) 65 throws PluginException { 66 mListener = listener; 67 mPlugin = plugin; 68 this.recommendsMultiVendorService = recommendsMultiVendorService; 69 70 // We handle any throwable to isolate our self from bugs in the plugin code. 71 // Cache simple properties to avoid having to deal with exceptions later in the code. 72 try { 73 name = Preconditions.checkArgumentPositive(mPlugin.getName(), "name"); 74 packageName = Preconditions.checkStringNotEmpty(mPlugin.getPackageName(), 75 "packageName"); 76 } catch (Throwable e) { 77 throw new PluginException(mPlugin, "Cannot cache simple properties ", e); 78 } 79 80 isRunning = false; 81 } 82 83 /** 84 * Start the plugin. From now on there might be callbacks to the registered listener. 85 */ start()86 public void start() 87 throws PluginException { 88 // We handle any throwable to isolate our self from bugs in the stub code 89 try { 90 synchronized (mLock) { 91 isRunning = true; 92 mPlugin.start(this); 93 } 94 } catch (Throwable e) { 95 throw new PluginException(mPlugin, "Cannot start", e); 96 } 97 } 98 99 /** 100 * Stop the plugin. From this call on there will not be any more callbacks. 101 */ stop()102 public void stop() throws PluginException { 103 // We handle any throwable to isolate our self from bugs in the stub code 104 try { 105 synchronized (mLock) { 106 mPlugin.stop(); 107 isRunning = false; 108 } 109 } catch (Throwable e) { 110 throw new PluginException(mPlugin, "Cannot stop", e); 111 } 112 } 113 114 /** 115 * Get the current number of printers reported by the stub. 116 * 117 * @return The number of printers reported by the stub. 118 */ getNumPrinters()119 public @IntRange(from = 0) int getNumPrinters() { 120 return mNumPrinters; 121 } 122 123 @Override onChanged(@ntRangefrom = 0) int numDiscoveredPrinters)124 public void onChanged(@IntRange(from = 0) int numDiscoveredPrinters) { 125 synchronized (mLock) { 126 Preconditions.checkState(isRunning); 127 128 mNumPrinters = Preconditions.checkArgumentNonnegative(numDiscoveredPrinters, 129 "numDiscoveredPrinters"); 130 131 if (mNumPrinters > 0) { 132 mListener.onChanged(); 133 } 134 } 135 } 136 137 /** 138 * Listener to listen for changes to {@link #getNumPrinters} 139 */ 140 public interface OnChangedListener { onChanged()141 void onChanged(); 142 } 143 144 /** 145 * Exception thrown if the stub has any issues. 146 */ 147 public class PluginException extends Exception { PluginException(PrintServicePlugin plugin, String message, Throwable e)148 private PluginException(PrintServicePlugin plugin, String message, Throwable e) { 149 super(plugin + ": " + message, e); 150 } 151 } 152 } 153