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