diff options
author | Svetoslav Ganov <svetoslavganov@google.com> | 2013-08-20 16:32:53 -0700 |
---|---|---|
committer | Svetoslav Ganov <svetoslavganov@google.com> | 2013-08-23 18:36:33 +0000 |
commit | 44720af55a8fdf991929983dad5d53c02851dd1e (patch) | |
tree | a8d00a35c432ab3f5fc19afe21e4492d28578645 /core/java/android/print | |
parent | 4359d56420b114f433ba4187c2d1f341bb35c938 (diff) | |
download | frameworks_base-44720af55a8fdf991929983dad5d53c02851dd1e.zip frameworks_base-44720af55a8fdf991929983dad5d53c02851dd1e.tar.gz frameworks_base-44720af55a8fdf991929983dad5d53c02851dd1e.tar.bz2 |
Print UI bug fixing and printer discovery refactoring.
1. Added support for selecting a printer from the all printers activity
that is not in the initial printer selection drop down. The user
initially sees a sub set of the printers in the drop down and the
last option is to see all printers in a separate activity. Some
of the printers in the all printers activity are not shown in the
initial drop down.
2. Refactored printer discovery by adding (private for now) printer
discovery app facing APIs. These APIs are needed to support multiple
printer selection activities (print dialog and all printers activities)
and also the settings for showing all printers for a service.
Now multiple apps can request observing for printers and there is
a centralized mediator that ensures the same printer discovery
session is used. The mediator dispatches printer discovery specific
requests to print services. It also aggregates discovered printers
and delivers them to the interested apps. The mediator minimizes
printer discovery session creation and starting and stopping discovery
by sharing the same discovery session and discovery window with
multiple apps. Lastly, the mediator takes care of print services
enabled during discovery by bringing them up to the current
discovery state (create discovery session and start discovery if
needed). The mediator also reports disappearing of the printers
of a service removed during discovery and notifies a newly
registered observers for the currnet printers if the observers are
added during an active printer discovery session.
3. Fixed bugs in the print UI and implemented some UX tweaks.
Change-Id: I4d0b0c5a6c6f1809b2ba5dbc8e9d63ab3d48f1ef
Diffstat (limited to 'core/java/android/print')
-rw-r--r-- | core/java/android/print/IPrintManager.aidl | 10 | ||||
-rw-r--r-- | core/java/android/print/IPrintSpooler.aidl | 6 | ||||
-rw-r--r-- | core/java/android/print/IPrintSpoolerClient.aidl | 8 | ||||
-rw-r--r-- | core/java/android/print/IPrinterDiscoveryObserver.aidl | 32 | ||||
-rw-r--r-- | core/java/android/print/PrintManager.java | 7 | ||||
-rw-r--r-- | core/java/android/print/PrinterDiscoverySession.java | 297 |
6 files changed, 346 insertions, 14 deletions
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl index 7155096..3bfd9a1 100644 --- a/core/java/android/print/IPrintManager.aidl +++ b/core/java/android/print/IPrintManager.aidl @@ -16,8 +16,10 @@ package android.print; +import android.print.IPrinterDiscoveryObserver; import android.print.IPrintDocumentAdapter; import android.print.IPrintClient; +import android.print.PrinterId; import android.print.PrintJobInfo; import android.print.PrintAttributes; @@ -34,4 +36,12 @@ interface IPrintManager { int appId, int userId); void cancelPrintJob(int printJobId, int appId, int userId); void restartPrintJob(int printJobId, int appId, int userId); + + void createPrinterDiscoverySession(in IPrinterDiscoveryObserver observer, int userId); + void startPrinterDiscovery(in IPrinterDiscoveryObserver observer, + in List<PrinterId> priorityList, int userId); + void stopPrinterDiscovery(in IPrinterDiscoveryObserver observer, int userId); + void requestPrinterUpdate(in PrinterId printerId, int userId); + void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer, + int userId); } diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl index 5c8a22a..0a77dab 100644 --- a/core/java/android/print/IPrintSpooler.aidl +++ b/core/java/android/print/IPrintSpooler.aidl @@ -18,7 +18,6 @@ package android.print; import android.content.ComponentName; import android.os.ParcelFileDescriptor; -import android.print.PrinterId; import android.print.IPrintDocumentAdapter; import android.print.IPrintClient; import android.print.IPrintSpoolerClient; @@ -47,9 +46,4 @@ oneway interface IPrintSpooler { int sequence); void writePrintJobData(in ParcelFileDescriptor fd, int printJobId); void setClient(IPrintSpoolerClient client); - - // Printer discovery APIs - void onPrintersAdded(in List<PrinterInfo> printers); - void onPrintersRemoved(in List<PrinterId> printerIds); - void onPrintersUpdated(in List<PrinterInfo> printerIds); } diff --git a/core/java/android/print/IPrintSpoolerClient.aidl b/core/java/android/print/IPrintSpoolerClient.aidl index da60120..8b511d6 100644 --- a/core/java/android/print/IPrintSpoolerClient.aidl +++ b/core/java/android/print/IPrintSpoolerClient.aidl @@ -17,7 +17,6 @@ package android.print; import android.content.ComponentName; -import android.print.PrinterId; import android.print.PrintJobInfo; @@ -30,11 +29,4 @@ oneway interface IPrintSpoolerClient { void onPrintJobQueued(in PrintJobInfo printJob); void onAllPrintJobsForServiceHandled(in ComponentName printService); void onAllPrintJobsHandled(); - - // Printer discovery APIs - void createPrinterDiscoverySession(); - void startPrinterDiscovery(in List<PrinterId> priorityList); - void stopPrinterDiscovery(); - void requestPrinterUpdate(in PrinterId printerId); - void destroyPrinterDiscoverySession(); } diff --git a/core/java/android/print/IPrinterDiscoveryObserver.aidl b/core/java/android/print/IPrinterDiscoveryObserver.aidl new file mode 100644 index 0000000..625f383 --- /dev/null +++ b/core/java/android/print/IPrinterDiscoveryObserver.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.print; + +import android.print.IPrintClient; +import android.print.PrinterId; +import android.print.PrinterInfo; + +/** + * Interface for observing discovered printers by a discovery session. + * + * @hide + */ +oneway interface IPrinterDiscoveryObserver { + void onPrintersAdded(in List<PrinterInfo> printers); + void onPrintersRemoved(in List<PrinterId> printerIds); + void onPrintersUpdated(in List<PrinterInfo> printerIds); +} diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index 531dcb2..d3e35c3 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -204,6 +204,13 @@ public final class PrintManager { return null; } + /** + * @hide + */ + public PrinterDiscoverySession createPrinterDiscoverySession() { + return new PrinterDiscoverySession(mService, mContext, mUserId); + } + private static final class PrintClient extends IPrintClient.Stub { private final WeakReference<PrintManager> mWeakPrintManager; diff --git a/core/java/android/print/PrinterDiscoverySession.java b/core/java/android/print/PrinterDiscoverySession.java new file mode 100644 index 0000000..8fbdd9c --- /dev/null +++ b/core/java/android/print/PrinterDiscoverySession.java @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.print; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.ArrayMap; +import android.util.Log; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @hide + */ +public final class PrinterDiscoverySession { + + private static final String LOG_TAG ="PrinterDiscoverySession"; + + private static final int MSG_PRINTERS_ADDED = 1; + private static final int MSG_PRINTERS_REMOVED = 2; + private static final int MSG_PRINTERS_UPDATED = 3; + + private final ArrayMap<PrinterId, PrinterInfo> mPrinters = + new ArrayMap<PrinterId, PrinterInfo>(); + + private final IPrintManager mPrintManager; + + private final int mUserId; + + private final Handler mHandler; + + private IPrinterDiscoveryObserver mObserver; + + private OnPrintersChangeListener mListener; + + private boolean mIsPrinterDiscoveryStarted; + + public static interface OnPrintersChangeListener { + public void onPrintersChanged(); + } + + PrinterDiscoverySession(IPrintManager printManager, Context context, int userId) { + mPrintManager = printManager; + mUserId = userId; + mHandler = new SessionHandler(context.getMainLooper()); + mObserver = new PrinterDiscoveryObserver(this); + try { + mPrintManager.createPrinterDiscoverySession(mObserver, mUserId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error creating printer discovery session", re); + } + } + + public final void startPrinterDisovery(List<PrinterId> priorityList) { + if (isDestroyed()) { + Log.w(LOG_TAG, "Ignoring start printers dsicovery - session destroyed"); + } + if (!mIsPrinterDiscoveryStarted) { + mIsPrinterDiscoveryStarted = true; + try { + mPrintManager.startPrinterDiscovery(mObserver, priorityList, mUserId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error starting printer discovery", re); + } + } + } + + public final void stopPrinterDiscovery() { + if (isDestroyed()) { + Log.w(LOG_TAG, "Ignoring stop printers discovery - session destroyed"); + } + if (mIsPrinterDiscoveryStarted) { + mIsPrinterDiscoveryStarted = false; + try { + mPrintManager.stopPrinterDiscovery(mObserver, mUserId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error stopping printer discovery", re); + } + } + } + + public final void requestPrinterUpdate(PrinterId printerId) { + if (isDestroyed()) { + Log.w(LOG_TAG, "Ignoring reqeust printer update - session destroyed"); + } + try { + mPrintManager.requestPrinterUpdate(printerId, mUserId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error requesting printer update", re); + } + } + + public final void destroy() { + if (isDestroyed()) { + Log.w(LOG_TAG, "Ignoring destroy - session destroyed"); + } + destroyNoCheck(); + } + + public final List<PrinterInfo> getPrinters() { + if (isDestroyed()) { + Log.w(LOG_TAG, "Ignoring get printers - session destroyed"); + return Collections.emptyList(); + } + return new ArrayList<PrinterInfo>(mPrinters.values()); + } + + public final boolean isDestroyed() { + throwIfNotCalledOnMainThread(); + return isDestroyedNoCheck(); + } + + public final boolean isPrinterDiscoveryStarted() { + throwIfNotCalledOnMainThread(); + return mIsPrinterDiscoveryStarted; + } + + public final void setOnPrintersChangeListener(OnPrintersChangeListener listener) { + throwIfNotCalledOnMainThread(); + mListener = listener; + } + + @Override + protected final void finalize() throws Throwable { + if (!isDestroyedNoCheck()) { + Log.e(LOG_TAG, "Destroying leaked printer discovery session"); + destroyNoCheck(); + } + super.finalize(); + } + + private boolean isDestroyedNoCheck() { + return (mObserver == null); + } + + private void destroyNoCheck() { + stopPrinterDiscovery(); + try { + mPrintManager.destroyPrinterDiscoverySession(mObserver, mUserId); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error destroying printer discovery session", re); + } finally { + mObserver = null; + mPrinters.clear(); + } + } + + private void handlePrintersAdded(List<PrinterInfo> printers) { + if (isDestroyed()) { + return; + } + boolean printersChanged = false; + final int addedPrinterCount = printers.size(); + for (int i = 0; i < addedPrinterCount; i++) { + PrinterInfo addedPrinter = printers.get(i); + if (mPrinters.get(addedPrinter.getId()) == null) { + mPrinters.put(addedPrinter.getId(), addedPrinter); + printersChanged = true; + } + } + if (printersChanged) { + notifyOnPrintersChanged(); + } + } + + private void handlePrintersRemoved(List<PrinterId> printerIds) { + if (isDestroyed()) { + return; + } + boolean printersChanged = false; + final int removedPrinterIdCount = printerIds.size(); + for (int i = 0; i < removedPrinterIdCount; i++) { + PrinterId removedPrinterId = printerIds.get(i); + if (mPrinters.remove(removedPrinterId) != null) { + printersChanged = true; + } + } + if (printersChanged) { + notifyOnPrintersChanged(); + } + } + + private void handlePrintersUpdated(List<PrinterInfo> printers) { + if (isDestroyed()) { + return; + } + boolean printersChanged = false; + final int updatedPrinterCount = printers.size(); + for (int i = 0; i < updatedPrinterCount; i++) { + PrinterInfo updatedPrinter = printers.get(i); + PrinterInfo oldPrinter = mPrinters.get(updatedPrinter.getId()); + if (oldPrinter != null && !oldPrinter.equals(updatedPrinter)) { + mPrinters.put(updatedPrinter.getId(), updatedPrinter); + printersChanged = true; + } + } + if (printersChanged) { + notifyOnPrintersChanged(); + } + } + + private void notifyOnPrintersChanged() { + if (mListener != null) { + mListener.onPrintersChanged(); + } + } + + private static void throwIfNotCalledOnMainThread() { + if (!Looper.getMainLooper().isCurrentThread()) { + throw new IllegalAccessError("must be called from the main thread"); + } + } + + private final class SessionHandler extends Handler { + + public SessionHandler(Looper looper) { + super(looper, null, false); + } + + @Override + @SuppressWarnings("unchecked") + public void handleMessage(Message message) { + switch (message.what) { + case MSG_PRINTERS_ADDED: { + List<PrinterInfo> printers = (List<PrinterInfo>) message.obj; + handlePrintersAdded(printers); + } break; + + case MSG_PRINTERS_REMOVED: { + List<PrinterId> printerIds = (List<PrinterId>) message.obj; + handlePrintersRemoved(printerIds); + } break; + + case MSG_PRINTERS_UPDATED: { + List<PrinterInfo> printers = (List<PrinterInfo>) message.obj; + handlePrintersUpdated(printers); + } break; + } + } + } + + private static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub { + + private final WeakReference<PrinterDiscoverySession> mWeakSession; + + public PrinterDiscoveryObserver(PrinterDiscoverySession session) { + mWeakSession = new WeakReference<PrinterDiscoverySession>(session); + } + + @Override + public void onPrintersAdded(List<PrinterInfo> printers) { + PrinterDiscoverySession session = mWeakSession.get(); + if (session != null) { + session.mHandler.obtainMessage(MSG_PRINTERS_ADDED, + printers).sendToTarget(); + } + } + + @Override + public void onPrintersRemoved(List<PrinterId> printerIds) { + PrinterDiscoverySession session = mWeakSession.get(); + if (session != null) { + session.mHandler.obtainMessage(MSG_PRINTERS_REMOVED, + printerIds).sendToTarget(); + } + } + + @Override + public void onPrintersUpdated(List<PrinterInfo> printers) { + PrinterDiscoverySession session = mWeakSession.get(); + if (session != null) { + session.mHandler.obtainMessage(MSG_PRINTERS_UPDATED, + printers).sendToTarget(); + } + } + } +} |