PrinterDiscoverySession.java revision 773f54de3de9bce7b6f915aa47ed686b161d77aa
1/* 2 * Copyright (C) 2013 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 17package android.print; 18 19import android.content.Context; 20import android.os.Handler; 21import android.os.Looper; 22import android.os.Message; 23import android.os.RemoteException; 24import android.util.ArrayMap; 25import android.util.Log; 26 27import java.lang.ref.WeakReference; 28import java.util.ArrayList; 29import java.util.Collections; 30import java.util.List; 31 32/** 33 * @hide 34 */ 35public final class PrinterDiscoverySession { 36 37 private static final String LOG_TAG ="PrinterDiscoverySession"; 38 39 private static final int MSG_PRINTERS_ADDED = 1; 40 private static final int MSG_PRINTERS_REMOVED = 2; 41 42 private final ArrayMap<PrinterId, PrinterInfo> mPrinters = 43 new ArrayMap<PrinterId, PrinterInfo>(); 44 45 private final IPrintManager mPrintManager; 46 47 private final int mUserId; 48 49 private final Handler mHandler; 50 51 private IPrinterDiscoveryObserver mObserver; 52 53 private OnPrintersChangeListener mListener; 54 55 private boolean mIsPrinterDiscoveryStarted; 56 57 public static interface OnPrintersChangeListener { 58 public void onPrintersChanged(); 59 } 60 61 PrinterDiscoverySession(IPrintManager printManager, Context context, int userId) { 62 mPrintManager = printManager; 63 mUserId = userId; 64 mHandler = new SessionHandler(context.getMainLooper()); 65 mObserver = new PrinterDiscoveryObserver(this); 66 try { 67 mPrintManager.createPrinterDiscoverySession(mObserver, mUserId); 68 } catch (RemoteException re) { 69 Log.e(LOG_TAG, "Error creating printer discovery session", re); 70 } 71 } 72 73 public final void startPrinterDisovery(List<PrinterId> priorityList) { 74 if (isDestroyed()) { 75 Log.w(LOG_TAG, "Ignoring start printers dsicovery - session destroyed"); 76 return; 77 } 78 if (!mIsPrinterDiscoveryStarted) { 79 mIsPrinterDiscoveryStarted = true; 80 try { 81 mPrintManager.startPrinterDiscovery(mObserver, priorityList, mUserId); 82 } catch (RemoteException re) { 83 Log.e(LOG_TAG, "Error starting printer discovery", re); 84 } 85 } 86 } 87 88 public final void stopPrinterDiscovery() { 89 if (isDestroyed()) { 90 Log.w(LOG_TAG, "Ignoring stop printers discovery - session destroyed"); 91 return; 92 } 93 if (mIsPrinterDiscoveryStarted) { 94 mIsPrinterDiscoveryStarted = false; 95 try { 96 mPrintManager.stopPrinterDiscovery(mObserver, mUserId); 97 } catch (RemoteException re) { 98 Log.e(LOG_TAG, "Error stopping printer discovery", re); 99 } 100 } 101 } 102 103 public final void startPrinterStateTracking(PrinterId printerId) { 104 if (isDestroyed()) { 105 Log.w(LOG_TAG, "Ignoring start printer state tracking - session destroyed"); 106 return; 107 } 108 try { 109 mPrintManager.startPrinterStateTracking(printerId, mUserId); 110 } catch (RemoteException re) { 111 Log.e(LOG_TAG, "Error starting printer state tracking", re); 112 } 113 } 114 115 public final void stopPrinterStateTracking(PrinterId printerId) { 116 if (isDestroyed()) { 117 Log.w(LOG_TAG, "Ignoring stop printer state tracking - session destroyed"); 118 return; 119 } 120 try { 121 mPrintManager.stopPrinterStateTracking(printerId, mUserId); 122 } catch (RemoteException re) { 123 Log.e(LOG_TAG, "Error stoping printer state tracking", re); 124 } 125 } 126 127 public final void validatePrinters(List<PrinterId> printerIds) { 128 if (isDestroyed()) { 129 Log.w(LOG_TAG, "Ignoring validate printers - session destroyed"); 130 return; 131 } 132 try { 133 mPrintManager.validatePrinters(printerIds, mUserId); 134 } catch (RemoteException re) { 135 Log.e(LOG_TAG, "Error validating printers", re); 136 } 137 } 138 139 public final void destroy() { 140 if (isDestroyed()) { 141 Log.w(LOG_TAG, "Ignoring destroy - session destroyed"); 142 } 143 destroyNoCheck(); 144 } 145 146 public final List<PrinterInfo> getPrinters() { 147 if (isDestroyed()) { 148 Log.w(LOG_TAG, "Ignoring get printers - session destroyed"); 149 return Collections.emptyList(); 150 } 151 return new ArrayList<PrinterInfo>(mPrinters.values()); 152 } 153 154 public final boolean isDestroyed() { 155 throwIfNotCalledOnMainThread(); 156 return isDestroyedNoCheck(); 157 } 158 159 public final boolean isPrinterDiscoveryStarted() { 160 throwIfNotCalledOnMainThread(); 161 return mIsPrinterDiscoveryStarted; 162 } 163 164 public final void setOnPrintersChangeListener(OnPrintersChangeListener listener) { 165 throwIfNotCalledOnMainThread(); 166 mListener = listener; 167 } 168 169 @Override 170 protected final void finalize() throws Throwable { 171 if (!isDestroyedNoCheck()) { 172 Log.e(LOG_TAG, "Destroying leaked printer discovery session"); 173 destroyNoCheck(); 174 } 175 super.finalize(); 176 } 177 178 private boolean isDestroyedNoCheck() { 179 return (mObserver == null); 180 } 181 182 private void destroyNoCheck() { 183 stopPrinterDiscovery(); 184 try { 185 mPrintManager.destroyPrinterDiscoverySession(mObserver, mUserId); 186 } catch (RemoteException re) { 187 Log.e(LOG_TAG, "Error destroying printer discovery session", re); 188 } finally { 189 mObserver = null; 190 mPrinters.clear(); 191 } 192 } 193 194 private void handlePrintersAdded(List<PrinterInfo> printers) { 195 if (isDestroyed()) { 196 return; 197 } 198 boolean printersChanged = false; 199 final int addedPrinterCount = printers.size(); 200 for (int i = 0; i < addedPrinterCount; i++) { 201 PrinterInfo addedPrinter = printers.get(i); 202 PrinterInfo oldPrinter = mPrinters.put(addedPrinter.getId(), addedPrinter); 203 if (oldPrinter == null || !oldPrinter.equals(addedPrinter)) { 204 printersChanged = true; 205 } 206 } 207 if (printersChanged) { 208 notifyOnPrintersChanged(); 209 } 210 } 211 212 private void handlePrintersRemoved(List<PrinterId> printerIds) { 213 if (isDestroyed()) { 214 return; 215 } 216 boolean printersChanged = false; 217 final int removedPrinterIdCount = printerIds.size(); 218 for (int i = 0; i < removedPrinterIdCount; i++) { 219 PrinterId removedPrinterId = printerIds.get(i); 220 if (mPrinters.remove(removedPrinterId) != null) { 221 printersChanged = true; 222 } 223 } 224 if (printersChanged) { 225 notifyOnPrintersChanged(); 226 } 227 } 228 229 private void notifyOnPrintersChanged() { 230 if (mListener != null) { 231 mListener.onPrintersChanged(); 232 } 233 } 234 235 private static void throwIfNotCalledOnMainThread() { 236 if (!Looper.getMainLooper().isCurrentThread()) { 237 throw new IllegalAccessError("must be called from the main thread"); 238 } 239 } 240 241 private final class SessionHandler extends Handler { 242 243 public SessionHandler(Looper looper) { 244 super(looper, null, false); 245 } 246 247 @Override 248 @SuppressWarnings("unchecked") 249 public void handleMessage(Message message) { 250 switch (message.what) { 251 case MSG_PRINTERS_ADDED: { 252 List<PrinterInfo> printers = (List<PrinterInfo>) message.obj; 253 handlePrintersAdded(printers); 254 } break; 255 256 case MSG_PRINTERS_REMOVED: { 257 List<PrinterId> printerIds = (List<PrinterId>) message.obj; 258 handlePrintersRemoved(printerIds); 259 } break; 260 } 261 } 262 } 263 264 private static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub { 265 266 private final WeakReference<PrinterDiscoverySession> mWeakSession; 267 268 public PrinterDiscoveryObserver(PrinterDiscoverySession session) { 269 mWeakSession = new WeakReference<PrinterDiscoverySession>(session); 270 } 271 272 @Override 273 public void onPrintersAdded(List<PrinterInfo> printers) { 274 PrinterDiscoverySession session = mWeakSession.get(); 275 if (session != null) { 276 session.mHandler.obtainMessage(MSG_PRINTERS_ADDED, 277 printers).sendToTarget(); 278 } 279 } 280 281 @Override 282 public void onPrintersRemoved(List<PrinterId> printerIds) { 283 PrinterDiscoverySession session = mWeakSession.get(); 284 if (session != null) { 285 session.mHandler.obtainMessage(MSG_PRINTERS_REMOVED, 286 printerIds).sendToTarget(); 287 } 288 } 289 } 290} 291