summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/os/RemoteCallbackList.java2
-rw-r--r--core/java/android/print/IPrintManager.aidl10
-rw-r--r--core/java/android/print/IPrintSpooler.aidl6
-rw-r--r--core/java/android/print/IPrintSpoolerClient.aidl8
-rw-r--r--core/java/android/print/IPrinterDiscoveryObserver.aidl32
-rw-r--r--core/java/android/print/PrintManager.java7
-rw-r--r--core/java/android/print/PrinterDiscoverySession.java297
-rw-r--r--packages/PrintSpooler/AndroidManifest.xml8
-rw-r--r--packages/PrintSpooler/res/layout/print_job_config_activity_content_editing.xml412
-rw-r--r--packages/PrintSpooler/res/values/strings.xml11
-rw-r--r--packages/PrintSpooler/res/values/styles.xml14
-rw-r--r--packages/PrintSpooler/res/values/themes.xml2
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java108
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java475
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java218
-rw-r--r--services/java/com/android/server/print/PrintManagerService.java80
-rw-r--r--services/java/com/android/server/print/RemotePrintService.java11
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java144
-rw-r--r--services/java/com/android/server/print/UserState.java655
20 files changed, 1636 insertions, 865 deletions
diff --git a/Android.mk b/Android.mk
index 998e65d..f606640 100644
--- a/Android.mk
+++ b/Android.mk
@@ -162,6 +162,7 @@ LOCAL_SRC_FILES += \
core/java/android/os/IVibratorService.aidl \
core/java/android/service/notification/INotificationListener.aidl \
core/java/android/print/ILayoutResultCallback.aidl \
+ core/java/android/print/IPrinterDiscoveryObserver.aidl \
core/java/android/print/IPrintDocumentAdapter.aidl \
core/java/android/print/IPrintClient.aidl \
core/java/android/print/IPrintManager.aidl \
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index c1d4ae9..d2a9cdc 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -18,8 +18,6 @@ package android.os;
import android.util.ArrayMap;
-import java.util.HashMap;
-
/**
* Takes care of the grunt work of maintaining a list of remote interfaces,
* typically for the use of performing callbacks from a
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();
+ }
+ }
+ }
+}
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 1f10af8..ab7ea09 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -18,12 +18,12 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.printspooler"
- android:sharedUserId="android.uid.system"
+ android:sharedUserId="android.uid.printspooler"
android:versionName="1"
android:versionCode="1"
coreApp="true">
- <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="17"/>
+ <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="18"/>
<uses-permission android:name="android.permission.ACCESS_ALL_PRINT_JOBS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
@@ -36,7 +36,8 @@
<application
android:allowClearUserData="false"
android:label="@string/app_label"
- android:allowBackup= "false">
+ android:allowBackup= "false"
+ android:supportsRtl="true">
<service
android:name=".PrintSpoolerService"
@@ -46,6 +47,7 @@
<activity
android:name=".PrintJobConfigActivity"
+ android:configChanges="orientation|screenSize"
android:exported="false"
android:theme="@style/PrintJobConfigActivityTheme">
</activity>
diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity_content_editing.xml b/packages/PrintSpooler/res/layout/print_job_config_activity_content_editing.xml
index 84c41de..252dd81 100644
--- a/packages/PrintSpooler/res/layout/print_job_config_activity_content_editing.xml
+++ b/packages/PrintSpooler/res/layout/print_job_config_activity_content_editing.xml
@@ -14,208 +14,234 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/content_editing"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:scrollbars="vertical"
+ android:background="@color/editable_background">
- <ScrollView
+ <GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:scrollbars="vertical"
- android:background="@color/editable_background">
+ android:columnCount="2">
- <GridLayout
+ <!-- Destination -->
+
+ <Spinner
+ android:id="@+id/destination_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="fill_horizontal"
+ android:layout_marginTop="24dip"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall">
+ </Spinner>
+
+ <!-- Copies -->
+
+ <view
+ class="com.android.printspooler.PrintJobConfigActivity$CustomEditText"
+ android:id="@+id/copies_edittext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="6dip"
+ android:layout_row="2"
+ android:layout_column="0"
+ android:layout_gravity="bottom|fill_horizontal"
+ style="@style/PrintOptionEditTextStyle"
+ android:inputType="numberDecimal">
+ </view>
+
+ <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginStart="36dip"
+ android:layout_marginEnd="6dip"
+ android:layout_row="1"
+ android:layout_column="0"
+ android:layout_gravity="start|bottom"
+ style="@style/PrintOptionTextViewStyle"
+ android:labelFor="@id/copies_edittext"
+ android:text="@string/label_copies">
+ </TextView>
+
+ <!-- Paper size -->
+
+ <Spinner
+ android:id="@+id/paper_size_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="6dip"
+ android:layout_marginEnd="24dip"
+ android:layout_row="2"
+ android:layout_column="1"
+ android:layout_gravity="fill_horizontal"
+ style="@style/PrintOptionSpinnerStyle">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginStart="18dip"
+ android:layout_marginEnd="24dip"
+ android:layout_row="1"
+ android:layout_column="1"
+ style="@style/PrintOptionTextViewStyle"
+ android:labelFor="@id/paper_size_spinner"
+ android:text="@string/label_paper_size">
+ </TextView>
+
+ <!-- Color -->
+
+ <Spinner
+ android:id="@+id/color_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
android:layout_marginStart="24dip"
- android:layout_marginTop="32dip"
+ android:layout_marginEnd="6dip"
+ android:layout_row="4"
+ android:layout_column="0"
+ android:layout_gravity="fill_horizontal"
+ style="@style/PrintOptionSpinnerStyle">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginStart="36dip"
+ android:layout_marginEnd="6dip"
+ android:layout_row="3"
+ android:layout_column="0"
+ style="@style/PrintOptionTextViewStyle"
+ android:labelFor="@id/color_spinner"
+ android:text="@string/label_color">
+ </TextView>
+
+ <!-- Orientation -->
+
+ <Spinner
+ android:id="@+id/orientation_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="6dip"
android:layout_marginEnd="24dip"
- android:layout_marginBottom="24dip"
- android:orientation="vertical"
- android:columnCount="2">
-
- <!-- Destination -->
-
- <Spinner
- android:id="@+id/destination_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="fill_horizontal"
- android:layout_row="0"
- android:layout_column="0"
- android:layout_columnSpan="2"
- android:minHeight="?android:attr/listPreferredItemHeightSmall">
- </Spinner>
-
- <!-- Copies -->
-
- <view
- class="com.android.printspooler.PrintJobConfigActivity$CustomEditText"
- android:id="@+id/copies_edittext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="6dip"
- android:layout_row="2"
- android:layout_column="0"
- android:layout_gravity="bottom"
- android:inputType="numberDecimal"
- android:selectAllOnFocus="true"
- android:minWidth="150dip"
- android:minHeight="?android:attr/listPreferredItemHeightSmall">
- </view>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginStart="12dip"
- android:layout_marginEnd="6dip"
- android:layout_row="1"
- android:layout_column="0"
- android:layout_gravity="start|bottom"
- android:labelFor="@id/copies_edittext"
- android:text="@string/label_copies"
- android:textAppearance="@style/PrintOptionTitleTextAppearance">
- </TextView>
-
- <!-- Paper size -->
-
- <Spinner
- android:id="@+id/paper_size_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="6dip"
- android:layout_row="2"
- android:layout_column="1"
- style="@style/PrintOptionSpinnerStyle">
- </Spinner>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginStart="18dip"
- android:layout_row="1"
- android:layout_column="1"
- android:labelFor="@id/paper_size_spinner"
- android:text="@string/label_paper_size"
- android:textAppearance="@style/PrintOptionTitleTextAppearance">
- </TextView>
-
- <!-- Color -->
-
- <Spinner
- android:id="@+id/color_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="6dip"
- android:layout_row="4"
- android:layout_column="0"
- style="@style/PrintOptionSpinnerStyle">
- </Spinner>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginStart="12dip"
- android:layout_marginEnd="6dip"
- android:layout_row="3"
- android:layout_column="0"
- android:labelFor="@id/color_spinner"
- android:text="@string/label_color"
- android:textAppearance="@style/PrintOptionTitleTextAppearance">
- </TextView>
-
- <!-- Orientation -->
-
- <Spinner
- android:id="@+id/orientation_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="6dip"
- android:layout_row="4"
- android:layout_column="1"
- style="@style/PrintOptionSpinnerStyle">
- </Spinner>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginStart="18dip"
- android:layout_row="3"
- android:layout_column="1"
- android:labelFor="@id/orientation_spinner"
- android:text="@string/label_orientation"
- android:textAppearance="@style/PrintOptionTitleTextAppearance">
- </TextView>
-
- <!-- Pages -->
-
- <Spinner
- android:id="@+id/range_options_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="6dip"
- android:layout_row="6"
- android:layout_column="0"
- style="@style/PrintOptionSpinnerStyle">
- </Spinner>
-
- <view
- class="com.android.printspooler.PrintJobConfigActivity$CustomEditText"
- android:id="@+id/page_range_edittext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginStart="6dip"
- android:layout_row="6"
- android:layout_column="1"
- android:layout_gravity="bottom"
- android:selectAllOnFocus="true"
- android:minWidth="150dip"
- android:hint="@string/pages_range_example"
- android:inputType="textNoSuggestions"
- android:visibility="gone"
- android:minHeight="?android:attr/listPreferredItemHeightSmall">
- </view>
-
- <TextView
- android:id="@+id/page_range_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginStart="12dip"
- android:layout_row="5"
- android:layout_column="0"
- android:labelFor="@id/range_options_spinner"
- android:text="@string/label_pages"
- android:textAppearance="@style/PrintOptionTitleTextAppearance">
- </TextView>
-
- </GridLayout>
-
- </ScrollView>
-
- <View
- android:layout_width="fill_parent"
- android:layout_height="1dip"
- android:background="@color/separator">
- </View>
-
- <Button
- android:id="@+id/print_button"
- style="?android:attr/buttonBarButtonStyle"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="fill_horizontal"
- android:text="@string/print_button"
- android:textSize="16sp"
- android:textColor="@color/important_text">
- </Button>
+ android:layout_row="4"
+ android:layout_column="1"
+ android:layout_gravity="fill_horizontal"
+ style="@style/PrintOptionSpinnerStyle">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginStart="18dip"
+ android:layout_marginEnd="24dip"
+ android:layout_row="3"
+ android:layout_column="1"
+ style="@style/PrintOptionTextViewStyle"
+ android:labelFor="@id/orientation_spinner"
+ android:text="@string/label_orientation">
+ </TextView>
+
+ <!-- Range options -->
+
+ <Spinner
+ android:id="@+id/range_options_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="6dip"
+ android:layout_row="6"
+ android:layout_column="0"
+ android:layout_gravity="fill_horizontal"
+ style="@style/PrintOptionSpinnerStyle">
+ </Spinner>
+
+ <TextView
+ android:id="@+id/range_options_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginStart="36dip"
+ android:layout_row="5"
+ android:layout_column="0"
+ style="@style/PrintOptionTextViewStyle"
+ android:labelFor="@id/range_options_spinner"
+ android:text="@string/label_pages">
+ </TextView>
+
+ <!-- Pages -->
+
+ <view
+ class="com.android.printspooler.PrintJobConfigActivity$CustomEditText"
+ android:id="@+id/page_range_edittext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="6dip"
+ android:layout_marginEnd="24dip"
+ android:layout_row="6"
+ android:layout_column="1"
+ android:layout_gravity="bottom|fill_horizontal"
+ style="@style/PrintOptionEditTextStyle"
+ android:visibility="gone"
+ android:inputType="textNoSuggestions">
+ </view>
+
+ <TextView
+ android:id="@+id/page_range_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginStart="12dip"
+ android:layout_marginEnd="24dip"
+ android:layout_row="5"
+ android:layout_column="1"
+ style="@style/PrintOptionTextViewStyle"
+ android:labelFor="@id/page_range_edittext"
+ android:text="@string/pages_range_example"
+ android:textAllCaps="false">
+ </TextView>
+
+ <!-- Print button -->
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="1dip"
+ android:layout_marginTop="24dip"
+ android:layout_row="7"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:layout_gravity="fill_horizontal"
+ android:background="@color/separator"
+ android:contentDescription="@null">
+ </ImageView>
+
+ <Button
+ android:id="@+id/print_button"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="fill_horizontal"
+ android:layout_row="8"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:text="@string/print_button"
+ android:textSize="16sp"
+ android:textColor="@color/important_text">
+ </Button>
+
+ </GridLayout>
+
+</ScrollView>
-</LinearLayout>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 41fc516..ee3cf84 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -22,6 +22,9 @@
<!-- Label of the print dialog's print button. [CHAR LIMIT=16] -->
<string name="print_button">Print</string>
+ <!-- Label of the print dialog's save button. [CHAR LIMIT=16] -->
+ <string name="save_button">Save</string>
+
<!-- Label of the destination widget. [CHAR LIMIT=20] -->
<string name="label_destination">DESTIINATION</string>
@@ -41,7 +44,7 @@
<string name="label_pages">PAGES (<xliff:g id="page_count" example="5">%1$s</xliff:g>)</string>
<!-- Page range exmple used as a hint of how to specify such. [CHAR LIMIT=15] -->
- <string name="pages_range_example">e.g. 1&#8211;5, 8</string>
+ <string name="pages_range_example">e.g. 1&#8211;5, 8, 11&#8211;13</string>
<!-- Title for the pring preview button .[CHAR LIMIT=30] -->
<string name="print_preview">Print preview</string>
@@ -62,11 +65,7 @@
<string name="save_as_pdf">Save as PDF</string>
<!-- Title for the open all printers UI option in the printer list. [CHAR LIMIT=30] -->
- <string name="all_printers">All printers\.\.\.</string>
-
- <!-- Title for the searching for printers option in the printer list
- (only option if not printers are available). [CHAR LIMIT=40] -->
- <string name="searching_for_printers">Searching for printers\.\.\.</string>
+ <string name="all_printers">All printers&#8230;</string>
<!-- Select printer activity -->
diff --git a/packages/PrintSpooler/res/values/styles.xml b/packages/PrintSpooler/res/values/styles.xml
index 702adf4..fe11c93 100644
--- a/packages/PrintSpooler/res/values/styles.xml
+++ b/packages/PrintSpooler/res/values/styles.xml
@@ -27,7 +27,21 @@
<item name="android:paddingTop">0dip</item>
<item name="android:paddingBottom">0dip</item>
<item name="android:minWidth">150dip</item>
+ <item name="android:maxWidth">200dip</item>
<item name="android:minHeight">?android:attr/listPreferredItemHeightSmall</item>
</style>
+ <style name="PrintOptionEditTextStyle">
+ <item name="android:selectAllOnFocus">true</item>
+ <item name="android:minHeight">?android:attr/listPreferredItemHeightSmall</item>
+ <item name="android:maxWidth">200dip</item>
+ <item name="android:singleLine">true</item>
+ <item name="android:ellipsize">end</item>
+ </style>
+
+ <style name="PrintOptionTextViewStyle">
+ <item name="android:textAppearance">@style/PrintOptionTitleTextAppearance</item>
+ <item name="android:maxWidth">200dip</item>
+ </style>
+
</resources>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 831b0ec..bb41527 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -18,7 +18,7 @@
<style name="PrintJobConfigActivityTheme" parent="@android:style/Theme.Holo.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
- <item name="android:windowSoftInputMode">stateAlwaysHidden|adjustPan</item>
+ <item name="android:windowSoftInputMode">stateAlwaysHidden|adjustResize</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:colorBackgroundCacheHint">@android:color/transparent</item>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
index 6bad5b3..28fd0e0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
@@ -21,6 +21,9 @@ import android.content.Context;
import android.content.Loader;
import android.os.AsyncTask;
import android.os.Build;
+import android.print.PrintManager;
+import android.print.PrinterDiscoverySession;
+import android.print.PrinterDiscoverySession.OnPrintersChangeListener;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.util.ArrayMap;
@@ -30,7 +33,6 @@ import android.util.Slog;
import android.util.Xml;
import com.android.internal.util.FastXmlSerializer;
-import com.android.printspooler.PrintSpoolerService.PrinterDiscoverySession;
import libcore.io.IoUtils;
@@ -62,7 +64,7 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
private static final int MAX_HISTORY_LENGTH = 50;
- private static final int MAX_HISTORICAL_PRINTER_COUNT = 4;
+ private static final int MAX_FAVORITE_PRINTER_COUNT = 4;
private final Map<PrinterId, PrinterInfo> mPrinters =
new LinkedHashMap<PrinterId, PrinterInfo>();
@@ -96,7 +98,7 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
@Override
protected void onStartLoading() {
if (DEBUG) {
- Log.i(LOG_TAG, "onStartLoading()");
+ Log.i(LOG_TAG, "onStartLoading()" + FusedPrintersProvider.this.hashCode());
}
// The contract is that if we already have a valid,
// result the we have to deliver it immediately.
@@ -113,7 +115,7 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
@Override
protected void onStopLoading() {
if (DEBUG) {
- Log.i(LOG_TAG, "onStopLoading()");
+ Log.i(LOG_TAG, "onStopLoading()" + FusedPrintersProvider.this.hashCode());
}
onCancelLoad();
}
@@ -121,7 +123,7 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
@Override
protected void onForceLoad() {
if (DEBUG) {
- Log.i(LOG_TAG, "onForceLoad()");
+ Log.i(LOG_TAG, "onForceLoad()" + FusedPrintersProvider.this.hashCode());
}
onCancelLoad();
loadInternal();
@@ -129,12 +131,21 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
private void loadInternal() {
if (mDiscoverySession == null) {
- mDiscoverySession = new MyPrinterDiscoverySession();
+ PrintManager printManager = (PrintManager) getContext()
+ .getSystemService(Context.PRINT_SERVICE);
+ mDiscoverySession = printManager.createPrinterDiscoverySession();
+ mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener() {
+ @Override
+ public void onPrintersChanged() {
+ deliverResult(new ArrayList<PrinterInfo>(
+ mDiscoverySession.getPrinters()));
+ }
+ });
mPersistenceManager.readPrinterHistory();
}
if (mPersistenceManager.isReadHistoryCompleted()
- && !mDiscoverySession.isStarted()) {
- final int favoriteCount = Math.min(MAX_HISTORICAL_PRINTER_COUNT,
+ && !mDiscoverySession.isPrinterDiscoveryStarted()) {
+ final int favoriteCount = Math.min(MAX_FAVORITE_PRINTER_COUNT,
mFavoritePrinters.size());
List<PrinterId> printerIds = new ArrayList<PrinterId>(favoriteCount);
for (int i = 0; i < favoriteCount; i++) {
@@ -147,13 +158,14 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
@Override
protected boolean onCancelLoad() {
if (DEBUG) {
- Log.i(LOG_TAG, "onCancelLoad()");
+ Log.i(LOG_TAG, "onCancelLoad()" + FusedPrintersProvider.this.hashCode());
}
return cancelInternal();
}
private boolean cancelInternal() {
- if (mDiscoverySession != null && mDiscoverySession.isStarted()) {
+ if (mDiscoverySession != null
+ && mDiscoverySession.isPrinterDiscoveryStarted()) {
mDiscoverySession.stopPrinterDiscovery();
return true;
} else if (mPersistenceManager.isReadHistoryInProgress()) {
@@ -165,7 +177,7 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
@Override
protected void onReset() {
if (DEBUG) {
- Log.i(LOG_TAG, "onReset()");
+ Log.i(LOG_TAG, "onReset()" + FusedPrintersProvider.this.hashCode());
}
onStopLoading();
mPrinters.clear();
@@ -178,73 +190,15 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
@Override
protected void onAbandon() {
if (DEBUG) {
- Log.i(LOG_TAG, "onAbandon()");
+ Log.i(LOG_TAG, "onAbandon()" + FusedPrintersProvider.this.hashCode());
}
onStopLoading();
}
public void refreshPrinter(PrinterId printerId) {
- if (isStarted() && mDiscoverySession != null && mDiscoverySession.isStarted()) {
- mDiscoverySession.requestPrinterUpdated(printerId);
- }
- }
-
- private final class MyPrinterDiscoverySession extends PrinterDiscoverySession {
-
- @Override
- public void onPrintersAdded(List<PrinterInfo> printers) {
- if (DEBUG) {
- Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersAdded()");
- }
- boolean printersAdded = false;
- final int addedPrinterCount = printers.size();
- for (int i = 0; i < addedPrinterCount; i++) {
- PrinterInfo printer = printers.get(i);
- if (!mPrinters.containsKey(printer.getId())) {
- mPrinters.put(printer.getId(), printer);
- printersAdded = true;
- }
- }
- if (printersAdded) {
- deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
- }
- }
-
- @Override
- public void onPrintersRemoved(List<PrinterId> printerIds) {
- if (DEBUG) {
- Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersRemoved()");
- }
- boolean removedPrinters = false;
- final int removedPrinterCount = printerIds.size();
- for (int i = 0; i < removedPrinterCount; i++) {
- PrinterId removedPrinterId = printerIds.get(i);
- if (mPrinters.remove(removedPrinterId) != null) {
- removedPrinters = true;
- }
- }
- if (removedPrinters) {
- deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
- }
- }
-
- @Override
- public void onPrintersUpdated(List<PrinterInfo> printers) {
- if (DEBUG) {
- Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersUpdated()");
- }
- boolean updatedPrinters = false;
- final int updatedPrinterCount = printers.size();
- for (int i = 0; i < updatedPrinterCount; i++) {
- PrinterInfo updatedPrinter = printers.get(i);
- if (mPrinters.containsKey(updatedPrinter.getId())) {
- mPrinters.put(updatedPrinter.getId(), updatedPrinter);
- updatedPrinters = true;
- }
- }
- if (updatedPrinters) {
- deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
- }
+ if (isStarted() && mDiscoverySession != null
+ && mDiscoverySession.isPrinterDiscoveryStarted()) {
+ mDiscoverySession.requestPrinterUpdate(printerId);
}
}
@@ -280,7 +234,7 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
@Override
protected void onPostExecute(List<PrinterInfo> printers) {
if (DEBUG) {
- Log.i(LOG_TAG, "read history completed");
+ Log.i(LOG_TAG, "read history completed" + FusedPrintersProvider.this.hashCode());
}
mHistoricalPrinters = printers;
@@ -290,7 +244,7 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
// We want the first few favorite printers on top of the list.
final int favoriteCount = Math.min(mFavoritePrinters.size(),
- MAX_HISTORICAL_PRINTER_COUNT);
+ MAX_FAVORITE_PRINTER_COUNT);
for (int i = 0; i < favoriteCount; i++) {
PrinterInfo favoritePrinter = mFavoritePrinters.get(i);
mPrinters.put(favoritePrinter.getId(), favoritePrinter);
@@ -299,6 +253,10 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
mReadHistoryInProgress = false;
mReadHistoryCompleted = true;
+ // Deliver the favorites.
+ deliverResult(mFavoritePrinters);
+
+ // Start loading the available printers.
loadInternal();
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index d3dd8c9..c01d8f8 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -64,7 +64,6 @@ import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
@@ -111,15 +110,10 @@ public class PrintJobConfigActivity extends Activity {
private static final int LOADER_ID_PRINTERS_LOADER = 1;
- private static final int DEST_ADAPTER_MIN_ITEM_COUNT = 2;
private static final int DEST_ADAPTER_MAX_ITEM_COUNT = 9;
- private static final int DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS = 0;
- private static final int DEST_ADAPTER_POSITION_SAVE_AS_PDF = 1;
-
private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
- private static final int DEST_ADAPTER_ITEM_ID_SEARCHING_FOR_PRINTERS = Integer.MAX_VALUE - 2;
private static final int ACTIVITY_REQUEST_CREATE_FILE = 1;
private static final int ACTIVITY_REQUEST_SELECT_PRINTER = 2;
@@ -196,15 +190,11 @@ public class PrintJobConfigActivity extends Activity {
setContentView(R.layout.print_job_config_activity_container);
- // TODO: This should be on the style
- getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
-
-
- mEditor = new Editor();
mDocument = new Document();
mController = new PrintController(new RemotePrintDocumentAdapter(
IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
PrintSpoolerService.peekInstance().generateFileForPrintJob(mPrintJobId)));
+ mEditor = new Editor();
try {
mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
@@ -218,6 +208,12 @@ public class PrintJobConfigActivity extends Activity {
}
@Override
+ public void onResume() {
+ super.onResume();
+ mEditor.refreshCurrentPrinter();
+ }
+
+ @Override
protected void onDestroy() {
// We can safely do the work in here since at this point
// the system is bound to our (spooler) process which
@@ -294,6 +290,8 @@ public class PrintJobConfigActivity extends Activity {
private int mControllerState = CONTROLLER_STATE_INITIALIZED;
+ private boolean mHasStarted;
+
private PageRange[] mRequestedPages;
public PrintController(RemotePrintDocumentAdapter adapter) {
@@ -305,6 +303,7 @@ public class PrintJobConfigActivity extends Activity {
}
public void initialize() {
+ mHasStarted = false;
mControllerState = CONTROLLER_STATE_INITIALIZED;
}
@@ -321,7 +320,7 @@ public class PrintJobConfigActivity extends Activity {
}
public boolean hasStarted() {
- return mControllerState >= CONTROLLER_STATE_STARTED;
+ return mHasStarted;
}
public boolean hasPerformedLayout() {
@@ -335,10 +334,14 @@ public class PrintJobConfigActivity extends Activity {
public void start() {
mControllerState = CONTROLLER_STATE_STARTED;
+ mHasStarted = true;
mRemotePrintAdapter.start();
}
public void update() {
+ if (!mController.hasStarted()) {
+ mController.start();
+ }
if (!printAttributesChanged()) {
// If the attributes changed, then we do not do a layout but may
// have to ask the app to write some pages. Hence, pretend layout
@@ -372,6 +375,7 @@ public class PrintJobConfigActivity extends Activity {
}
if (isCancelled()) {
+ mEditor.updateUi();
if (mEditor.isDone()) {
PrintJobConfigActivity.this.finish();
}
@@ -379,7 +383,6 @@ public class PrintJobConfigActivity extends Activity {
}
mControllerState = CONTROLLER_STATE_LAYOUT_COMPLETED;
- mEditor.updateUi();
// If the info changed, we update the document and the print job.
final boolean infoChanged = !info.equals(mDocument.info);
@@ -402,6 +405,7 @@ public class PrintJobConfigActivity extends Activity {
// trigger an update.
mRequestedPages = mEditor.getRequestedPages();
if (mRequestedPages == null) {
+ mEditor.updateUi();
if (mEditor.isDone()) {
PrintJobConfigActivity.this.finish();
}
@@ -423,12 +427,15 @@ public class PrintJobConfigActivity extends Activity {
// preview button, then just skip the write.
if (!LIVE_PREVIEW_SUPPORTED && !mEditor.isPreviewConfirmed()
&& mMetadata.getBoolean(PrintDocumentAdapter.METADATA_KEY_PRINT_PREVIEW)) {
+ mEditor.updateUi();
if (mEditor.isDone()) {
PrintJobConfigActivity.this.finish();
}
return;
}
+ mEditor.updateUi();
+
// Request a write of the pages of interest.
mControllerState = CONTROLLER_STATE_WRITE_STARTED;
mRemotePrintAdapter.write(mRequestedPages, mWriteResultCallback,
@@ -647,7 +654,6 @@ public class PrintJobConfigActivity extends Activity {
if (resultCode == RESULT_OK) {
PrinterId printerId = (PrinterId) data.getParcelableExtra(
INTENT_EXTRA_PRINTER_ID);
- // TODO: Make sure the selected printer is in the shown list.
mEditor.selectPrinter(printerId);
}
} break;
@@ -704,8 +710,9 @@ public class PrintJobConfigActivity extends Activity {
private EditText mCopiesEditText;
- private TextView mRangeTitle;
- private EditText mRangeEditText;
+ private TextView mRangeOptionsTitle;
+ private TextView mPageRangeTitle;
+ private EditText mPageRangeEditText;
private Spinner mDestinationSpinner;
private final DestinationAdapter mDestinationSpinnerAdapter;
@@ -729,6 +736,8 @@ public class PrintJobConfigActivity extends Activity {
private Button mPrintButton;
+ private PrinterInfo mCurrentPrinter;
+
private final OnItemSelectedListener mOnItemSelectedListener =
new AdapterView.OnItemSelectedListener() {
@Override
@@ -738,69 +747,37 @@ public class PrintJobConfigActivity extends Activity {
mIgnoreNextDestinationChange = false;
return;
}
+
if (id == DEST_ADAPTER_ITEM_ID_ALL_PRINTERS) {
- mIgnoreNextDestinationChange = true;
- mDestinationSpinner.setSelection(0);
- Intent intent = new Intent(PrintJobConfigActivity.this,
- SelectPrinterActivity.class);
- startActivityForResult(intent, ACTIVITY_REQUEST_SELECT_PRINTER);
+ startSelectPrinterActivity();
return;
}
- mWaitingForPrinterCapabilities = false;
+
mCurrPrintAttributes.clear();
+
PrinterInfo printer = (PrinterInfo) mDestinationSpinnerAdapter
.getItem(position);
+
+ PrintSpoolerService.peekInstance().setPrintJobPrinterNoPersistence(
+ mPrintJobId, printer);
+
if (printer != null) {
- PrintSpoolerService.peekInstance().setPrintJobPrinterNoPersistence(
- mPrintJobId, printer);
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
if (capabilities == null) {
- List<PrinterId> printerIds = new ArrayList<PrinterId>();
- printerIds.add(printer.getId());
- FusedPrintersProvider printersLoader = (FusedPrintersProvider)
- (Loader<?>) getLoaderManager().getLoader(
- LOADER_ID_PRINTERS_LOADER);
- if (printersLoader != null) {
- printersLoader.refreshPrinter(printer.getId());
- }
- mWaitingForPrinterCapabilities = true;
//TODO: We need a timeout for the update.
+ mEditor.refreshCurrentPrinter();
} else {
capabilities.getDefaults(mCurrPrintAttributes);
if (!mController.hasStarted()) {
mController.start();
}
- if (!hasErrors()) {
- mController.update();
- }
+ mController.update();
}
}
- // The printer changed so we want to start with a clean slate
- // for the print options and let them be populated from the
- // printer capabilities and use the printer defaults.
- if (!mMediaSizeSpinnerAdapter.isEmpty()) {
- mIgnoreNextMediaSizeChange = true;
- mMediaSizeSpinnerAdapter.clear();
- }
- if (!mColorModeSpinnerAdapter.isEmpty()) {
- mIgnoreNextColorModeChange = true;
- mColorModeSpinnerAdapter.clear();
- }
- if (!mOrientationSpinnerAdapter.isEmpty()) {
- mIgnoreNextOrientationChange = true;
- mOrientationSpinnerAdapter.clear();
- }
- if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
- mIgnoreNextRangeOptionChange = true;
- mRangeOptionsSpinner.setSelection(0);
- }
- if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
- mIgnoreNextCopiesChange = true;
- mCopiesEditText.setText(MIN_COPIES_STRING);
- }
+ mCurrentPrinter = printer;
- updateUi();
+ updateUiForNewPrinterCapabilities();
} else if (spinner == mMediaSizeSpinner) {
if (mIgnoreNextMediaSizeChange) {
mIgnoreNextMediaSizeChange = false;
@@ -877,7 +854,13 @@ public class PrintJobConfigActivity extends Activity {
return;
}
- final int copies = Integer.parseInt(editable.toString());
+ int copies = 0;
+ try {
+ copies = Integer.parseInt(editable.toString());
+ } catch (NumberFormatException nfe) {
+ /* ignore */
+ }
+
if (copies < MIN_COPIES) {
mCopiesEditText.setError("");
updateUi();
@@ -918,14 +901,14 @@ public class PrintJobConfigActivity extends Activity {
String text = editable.toString();
if (TextUtils.isEmpty(text)) {
- mRangeEditText.setError("");
+ mPageRangeEditText.setError("");
updateUi();
return;
}
String escapedText = PATTERN_ESCAPE_SPECIAL_CHARS.matcher(text).replaceAll("////");
if (!PATTERN_PAGE_RANGE.matcher(escapedText).matches()) {
- mRangeEditText.setError("");
+ mPageRangeEditText.setError("");
updateUi();
return;
}
@@ -935,7 +918,7 @@ public class PrintJobConfigActivity extends Activity {
String numericString = text.substring(matcher.start(), matcher.end());
final int pageIndex = Integer.parseInt(numericString);
if (pageIndex < 1 || pageIndex > mDocument.info.getPageCount()) {
- mRangeEditText.setError("");
+ mPageRangeEditText.setError("");
updateUi();
return;
}
@@ -943,7 +926,7 @@ public class PrintJobConfigActivity extends Activity {
//TODO: Catch the error if start is less grater than the end.
- mRangeEditText.setError(null);
+ mPageRangeEditText.setError(null);
mPrintButton.setEnabled(true);
updateUi();
@@ -963,45 +946,70 @@ public class PrintJobConfigActivity extends Activity {
private boolean mIgnoreNextCopiesChange;
private boolean mIgnoreNextRangeChange;
- private boolean mWaitingForPrinterCapabilities;
-
private int mCurrentUi = UI_NONE;
+ private boolean mFavoritePrinterSelected;
+
public Editor() {
// Destination.
mDestinationSpinnerAdapter = new DestinationAdapter();
mDestinationSpinnerAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
- final int selectedPosition = mDestinationSpinner.getSelectedItemPosition();
- if (mDestinationSpinnerAdapter.getCount() > 0) {
- // Make sure we select the first printer if we have data.
- if (selectedPosition == AdapterView.INVALID_POSITION) {
- mDestinationSpinner.setSelection(0);
- }
- } else {
- // Make sure we select no printer if we have no data.
- mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
+ // Initially, we have only sage to PDF as a printer but after some
+ // printers are loaded we want to select the user's favorite one
+ // which is the first.
+ if (!mFavoritePrinterSelected && mDestinationSpinnerAdapter.getCount() > 2) {
+ mFavoritePrinterSelected = true;
+ mDestinationSpinner.setSelection(0);
}
- // Maybe we did not have capabilities when the current printer was
- // selected, but now the selected printer has capabilities. Generate
- // a fake selection so the code in the selection change handling takes
- // care of updating everything. This way the logic is in one place.
- if (mWaitingForPrinterCapabilities) {
- mWaitingForPrinterCapabilities = false;
- PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
- if (printer != null && printer.getCapabilities() != null) {
- mOnItemSelectedListener.onItemSelected(mDestinationSpinner, null,
- selectedPosition, selectedPosition);
+ // If the current printer properties changed, we update the UI.
+ if (mCurrentPrinter != null) {
+ final int printerCount = mDestinationSpinnerAdapter.getCount();
+ for (int i = 0; i < printerCount; i++) {
+ Object item = mDestinationSpinnerAdapter.getItem(i);
+ // Some items are not printers
+ if (item instanceof PrinterInfo) {
+ PrinterInfo printer = (PrinterInfo) item;
+ if (!printer.getId().equals(mCurrentPrinter.getId())) {
+ continue;
+ }
+
+ // Update the UI if capabilities changed.
+ boolean capabilitiesChanged = false;
+
+ if (mCurrentPrinter.getCapabilities() == null) {
+ if (printer.getCapabilities() != null) {
+ capabilitiesChanged = true;
+ }
+ } else if (!mCurrentPrinter.getCapabilities().equals(
+ printer.getCapabilities())) {
+ capabilitiesChanged = true;
+ }
+
+ if (capabilitiesChanged) {
+ // Update the current printer.
+ mCurrentPrinter.copyFrom(printer);
+
+ // If something changed during UI update...
+ if (updateUi()) {
+ // Update current attributes.
+ printer.getCapabilities().getDefaults(mCurrPrintAttributes);
+ // Update the document.
+ mController.update();
+ }
+ }
+
+ break;
+ }
}
}
- updateUi();
}
@Override
public void onInvalidated() {
- updateUi();
+ updateUiForNewPrinterCapabilities();
}
});
@@ -1039,17 +1047,24 @@ public class PrintJobConfigActivity extends Activity {
updateUi();
}
- public void selectPrinter(PrinterId printerId) {
- final int printerCount = mDestinationSpinnerAdapter.getCount();
- for (int i = 0; i < printerCount; i++) {
- PrinterInfo printer = (PrinterInfo) mDestinationSpinnerAdapter.getItem(i);
- if (printer.getId().equals(printerId)) {
- mDestinationSpinner.setSelection(i);
- return;
+ public void refreshCurrentPrinter() {
+ PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
+ if (printer != null) {
+ FusedPrintersProvider printersLoader = (FusedPrintersProvider)
+ (Loader<?>) getLoaderManager().getLoader(
+ LOADER_ID_PRINTERS_LOADER);
+ if (printersLoader != null) {
+ printersLoader.refreshPrinter(printer.getId());
}
}
}
+ public void selectPrinter(PrinterId printerId) {
+ mDestinationSpinnerAdapter.ensurePrinterShownPrinterShown(printerId);
+ final int position = mDestinationSpinnerAdapter.getPrinterIndex(printerId);
+ mDestinationSpinner.setSelection(position);
+ }
+
public boolean isPrintingToPdf() {
return mDestinationSpinner.getSelectedItem()
== mDestinationSpinnerAdapter.mFakePdfPrinter;
@@ -1163,12 +1178,7 @@ public class PrintJobConfigActivity extends Activity {
mEditor.confirmPrint();
mController.update();
if (!printer.equals(mDestinationSpinnerAdapter.mFakePdfPrinter)) {
- FusedPrintersProvider printersLoader = (FusedPrintersProvider)
- (Loader<?>) getLoaderManager().getLoader(
- LOADER_ID_PRINTERS_LOADER);
- if (printersLoader != null) {
- printersLoader.addHistoricalPrinter(printer);
- }
+ mEditor.refreshCurrentPrinter();
}
} else {
mEditor.cancel();
@@ -1288,7 +1298,7 @@ public class PrintJobConfigActivity extends Activity {
}
if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
List<PageRange> pageRanges = new ArrayList<PageRange>();
- mStringCommaSplitter.setString(mRangeEditText.getText().toString());
+ mStringCommaSplitter.setString(mPageRangeEditText.getText().toString());
while (mStringCommaSplitter.hasNext()) {
String range = mStringCommaSplitter.next().trim();
@@ -1340,7 +1350,7 @@ public class PrintJobConfigActivity extends Activity {
mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
- if (mDestinationSpinnerAdapter.getCount() > 0) {
+ if (mDestinationSpinnerAdapter.getCount() > 0 && mController.hasStarted()) {
mIgnoreNextDestinationChange = true;
}
@@ -1368,12 +1378,8 @@ public class PrintJobConfigActivity extends Activity {
mIgnoreNextOrientationChange = true;
}
- // Range
- mRangeTitle = (TextView) findViewById(R.id.page_range_title);
- mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
- mRangeEditText.addTextChangedListener(mRangeTextWatcher);
-
// Range options
+ mRangeOptionsTitle = (TextView) findViewById(R.id.range_options_title);
mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
mRangeOptionsSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
@@ -1381,14 +1387,19 @@ public class PrintJobConfigActivity extends Activity {
mIgnoreNextRangeOptionChange = true;
}
+ // Page range
+ mPageRangeTitle = (TextView) findViewById(R.id.page_range_title);
+ mPageRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
+ mPageRangeEditText.addTextChangedListener(mRangeTextWatcher);
+
// Print button
mPrintButton = (Button) findViewById(R.id.print_button);
registerPrintButtonClickListener();
}
- public void updateUi() {
+ public boolean updateUi() {
if (mCurrentUi != UI_EDITING_PRINT_JOB) {
- return;
+ return false;
}
if (isPrintConfirmed() || isPreviewConfirmed() || isCancelled()) {
mDestinationSpinner.setEnabled(false);
@@ -1397,11 +1408,11 @@ public class PrintJobConfigActivity extends Activity {
mColorModeSpinner.setEnabled(false);
mOrientationSpinner.setEnabled(false);
mRangeOptionsSpinner.setEnabled(false);
- mRangeEditText.setEnabled(false);
+ mPageRangeEditText.setEnabled(false);
// TODO: Remove entirely or implement print preview.
// mPrintPreviewButton.setEnabled(false);
mPrintButton.setEnabled(false);
- return;
+ return false;
}
// If a printer with capabilities is selected, then we enabled all options.
@@ -1452,15 +1463,16 @@ public class PrintJobConfigActivity extends Activity {
mRangeOptionsSpinner.setSelection(0);
}
mRangeOptionsSpinner.setEnabled(false);
- mRangeTitle.setText(getString(R.string.label_pages,
+ mRangeOptionsTitle.setText(getString(R.string.label_pages,
getString(R.string.page_count_unknown)));
- if (!TextUtils.equals(mRangeEditText.getText(), "")) {
+ if (!TextUtils.equals(mPageRangeEditText.getText(), "")) {
mIgnoreNextRangeChange = true;
- mRangeEditText.setText("");
+ mPageRangeEditText.setText("");
}
- mRangeEditText.setEnabled(false);
- mRangeEditText.setVisibility(View.INVISIBLE);
+ mPageRangeEditText.setEnabled(false);
+ mPageRangeEditText.setVisibility(View.INVISIBLE);
+ mPageRangeTitle.setVisibility(View.INVISIBLE);
// // Print preview
// mPrintPreviewButton.setEnabled(false);
@@ -1468,17 +1480,20 @@ public class PrintJobConfigActivity extends Activity {
// Print
mPrintButton.setEnabled(false);
+
+ return false;
} else {
+ boolean someAttributeSelectionChanged = false;
+
PrintAttributes defaultAttributes = mTempPrintAttributes;
PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
printer.getCapabilities().getDefaults(defaultAttributes);
- // Copies
- mCopiesEditText.setEnabled(true);
-
// Media size.
List<MediaSize> mediaSizes = capabilities.getMediaSizes();
+
+ // If the media sizes changed, we update the adapter and the spinner.
boolean mediaSizesChanged = false;
final int mediaSizeCount = mediaSizes.size();
if (mediaSizeCount != mMediaSizeSpinnerAdapter.getCount()) {
@@ -1492,22 +1507,40 @@ public class PrintJobConfigActivity extends Activity {
}
}
if (mediaSizesChanged) {
+ // Remember the old media size to try selecting it again.
+ int oldMediaSizeNewIndex = AdapterView.INVALID_POSITION;
+ MediaSize oldMediaSize = mCurrPrintAttributes.getMediaSize();
+
+ // Rebuild the adapter data.
mMediaSizeSpinnerAdapter.clear();
for (int i = 0; i < mediaSizeCount; i++) {
MediaSize mediaSize = mediaSizes.get(i);
+ if (mediaSize.equals(oldMediaSize)) {
+ // Update the index of the old selection.
+ oldMediaSizeNewIndex = i;
+ }
mMediaSizeSpinnerAdapter.add(new SpinnerItem<MediaSize>(
mediaSize, mediaSize.getLabel()));
}
+
if (mediaSizeCount <= 0) {
+ // No media sizes - clear the selection.
mMediaSizeSpinner.setEnabled(false);
- mMediaSizeSpinner.setSelection(AdapterView.INVALID_POSITION);
+ // Clear selection and mark if selection changed.
+ someAttributeSelectionChanged = setMediaSizeSpinnerSelectionNoCallback(
+ AdapterView.INVALID_POSITION);
} else {
mMediaSizeSpinner.setEnabled(true);
- final int selectedMediaSizeIndex = Math.max(mediaSizes.indexOf(
- defaultAttributes.getMediaSize()), 0);
- if (mMediaSizeSpinner.getSelectedItemPosition() != selectedMediaSizeIndex) {
- mIgnoreNextMediaSizeChange = true;
- mMediaSizeSpinner.setSelection(selectedMediaSizeIndex);
+
+ if (oldMediaSizeNewIndex != AdapterView.INVALID_POSITION) {
+ // Select the old media size - nothing really changed.
+ setMediaSizeSpinnerSelectionNoCallback(oldMediaSizeNewIndex);
+ } else {
+ // Select the first or the default and mark if selection changed.
+ final int mediaSizeIndex = Math.max(mediaSizes.indexOf(
+ defaultAttributes.getMediaSize()), 0);
+ someAttributeSelectionChanged = setMediaSizeSpinnerSelectionNoCallback(
+ mediaSizeIndex);
}
}
}
@@ -1619,20 +1652,22 @@ public class PrintJobConfigActivity extends Activity {
|| info.getPageCount() == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)) {
mRangeOptionsSpinner.setEnabled(true);
if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
- if (!mRangeEditText.isEnabled()) {
- mRangeEditText.setEnabled(true);
- mRangeEditText.setVisibility(View.VISIBLE);
- mRangeEditText.requestFocus();
+ if (!mPageRangeEditText.isEnabled()) {
+ mPageRangeEditText.setEnabled(true);
+ mPageRangeEditText.setVisibility(View.VISIBLE);
+ mPageRangeTitle.setVisibility(View.VISIBLE);
+ mPageRangeEditText.requestFocus();
InputMethodManager imm = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
- imm.showSoftInput(mRangeEditText, 0);
+ imm.showSoftInput(mPageRangeEditText, 0);
}
} else {
- mRangeEditText.setEnabled(false);
- mRangeEditText.setVisibility(View.INVISIBLE);
+ mPageRangeEditText.setEnabled(false);
+ mPageRangeEditText.setVisibility(View.INVISIBLE);
+ mPageRangeTitle.setVisibility(View.INVISIBLE);
}
final int pageCount = mDocument.info.getPageCount();
- mRangeTitle.setText(getString(R.string.label_pages,
+ mRangeOptionsTitle.setText(getString(R.string.label_pages,
(pageCount == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)
? getString(R.string.page_count_unknown)
: String.valueOf(pageCount)));
@@ -1642,16 +1677,29 @@ public class PrintJobConfigActivity extends Activity {
mRangeOptionsSpinner.setSelection(0);
}
mRangeOptionsSpinner.setEnabled(false);
- mRangeTitle.setText(getString(R.string.label_pages,
+ mRangeOptionsTitle.setText(getString(R.string.label_pages,
getString(R.string.page_count_unknown)));
- mRangeEditText.setEnabled(false);
- mRangeEditText.setVisibility(View.INVISIBLE);
+ mPageRangeEditText.setEnabled(false);
+ mPageRangeEditText.setVisibility(View.INVISIBLE);
+ mPageRangeTitle.setVisibility(View.INVISIBLE);
}
mRangeOptionsSpinner.setEnabled(true);
// Print/Print preview
+ if (mDestinationSpinner.getSelectedItemId()
+ != DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF) {
+ String newText = getString(R.string.print_button);
+ if (!TextUtils.equals(newText, mPrintButton.getText())) {
+ mPrintButton.setText(R.string.print_button);
+ }
+ } else {
+ String newText = getString(R.string.save_button);
+ if (!TextUtils.equals(newText, mPrintButton.getText())) {
+ mPrintButton.setText(R.string.save_button);
+ }
+ }
if ((mRangeOptionsSpinner.getSelectedItemPosition() == 1
- && (TextUtils.isEmpty(mRangeEditText.getText()) || hasErrors()))
+ && (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
|| (mRangeOptionsSpinner.getSelectedItemPosition() == 0
&& (!mController.hasPerformedLayout() || hasErrors()))) {
// mPrintPreviewButton.setEnabled(false);
@@ -1667,6 +1715,12 @@ public class PrintJobConfigActivity extends Activity {
}
// Copies
+ if (mDestinationSpinner.getSelectedItemId()
+ != DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF) {
+ mCopiesEditText.setEnabled(true);
+ } else {
+ mCopiesEditText.setEnabled(false);
+ }
if (mCopiesEditText.getError() == null
&& TextUtils.isEmpty(mCopiesEditText.getText())) {
mIgnoreNextCopiesChange = true;
@@ -1674,13 +1728,62 @@ public class PrintJobConfigActivity extends Activity {
mCopiesEditText.selectAll();
mCopiesEditText.requestFocus();
}
- mCopiesEditText.setEnabled(true);
+
+ return someAttributeSelectionChanged;
+ }
+ }
+
+ private boolean setMediaSizeSpinnerSelectionNoCallback(int position) {
+ if (mMediaSizeSpinner.getSelectedItemPosition() != position) {
+ mIgnoreNextMediaSizeChange = true;
+ mMediaSizeSpinner.setSelection(position);
+ return true;
+ }
+ return false;
+ }
+
+ private void updateUiForNewPrinterCapabilities() {
+ // The printer changed so we want to start with a clean slate
+ // for the print options and let them be populated from the
+ // printer capabilities and use the printer defaults.
+ if (!mMediaSizeSpinnerAdapter.isEmpty()) {
+ mIgnoreNextMediaSizeChange = true;
+ mMediaSizeSpinnerAdapter.clear();
+ }
+ if (!mColorModeSpinnerAdapter.isEmpty()) {
+ mIgnoreNextColorModeChange = true;
+ mColorModeSpinnerAdapter.clear();
}
+ if (!mOrientationSpinnerAdapter.isEmpty()) {
+ mIgnoreNextOrientationChange = true;
+ mOrientationSpinnerAdapter.clear();
+ }
+ if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
+ mIgnoreNextRangeOptionChange = true;
+ mRangeOptionsSpinner.setSelection(0);
+ }
+ if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
+ mIgnoreNextCopiesChange = true;
+ mCopiesEditText.setText(MIN_COPIES_STRING);
+ }
+
+ updateUi();
+ }
+
+ private void startSelectPrinterActivity() {
+ mIgnoreNextDestinationChange = true;
+ mDestinationSpinner.setSelection(0);
+ Intent intent = new Intent(PrintJobConfigActivity.this,
+ SelectPrinterActivity.class);
+ startActivityForResult(intent, ACTIVITY_REQUEST_SELECT_PRINTER);
}
private boolean hasErrors() {
- return mRangeEditText.getError() != null
- || mCopiesEditText.getError() != null;
+ if (mCopiesEditText.getError() != null) {
+ return true;
+ }
+ return mPageRangeEditText.getVisibility() == View.VISIBLE
+ && mPageRangeEditText.getError() != null;
}
// private boolean hasPdfViewer() {
@@ -1708,29 +1811,49 @@ public class PrintJobConfigActivity extends Activity {
implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>{
private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
- public final PrinterInfo mFakePdfPrinter;
+ private final PrinterInfo mFakePdfPrinter;
+
+ private PrinterId mLastShownPrinterId;
public DestinationAdapter() {
getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
mFakePdfPrinter = createFakePdfPrinter();
}
+ public int getPrinterIndex(PrinterId printerId) {
+ for (int i = 0; i < getCount(); i++) {
+ PrinterInfo printer = (PrinterInfo) getItem(i);
+ if (printer != null && printer.getId().equals(printerId)) {
+ return i;
+ }
+ }
+ return AdapterView.INVALID_POSITION;
+ }
+
+ public void ensurePrinterShownPrinterShown(PrinterId printerId) {
+ mLastShownPrinterId = printerId;
+ ensureLastShownPrinterInPosition();
+ }
+
@Override
public int getCount() {
- return Math.max(Math.min(mPrinters.size(), DEST_ADAPTER_MAX_ITEM_COUNT),
- DEST_ADAPTER_MIN_ITEM_COUNT);
+ return Math.min(mPrinters.size() + 2, DEST_ADAPTER_MAX_ITEM_COUNT);
}
@Override
public Object getItem(int position) {
- if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
- return mFakePdfPrinter;
- }
- if (!mPrinters.isEmpty()) {
- if (position < DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+ if (mPrinters.isEmpty()) {
+ if (position == 0) {
+ return mFakePdfPrinter;
+ }
+ } else {
+ if (position < 1) {
return mPrinters.get(position);
- } else if (position > DEST_ADAPTER_POSITION_SAVE_AS_PDF
- && position < getCount() - 1) {
+ }
+ if (position == 1) {
+ return mFakePdfPrinter;
+ }
+ if (position < getCount() - 1) {
return mPrinters.get(position - 1);
}
}
@@ -1739,15 +1862,17 @@ public class PrintJobConfigActivity extends Activity {
@Override
public long getItemId(int position) {
- if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
- return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
- }
if (mPrinters.isEmpty()) {
- if (position == DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS) {
- return DEST_ADAPTER_ITEM_ID_SEARCHING_FOR_PRINTERS;
+ if (position == 0) {
+ return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
+ }
+ } else {
+ if (position == 1) {
+ return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
+ }
+ if (position == getCount() - 1) {
+ return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
}
- } else if (position == getCount() - 1) {
- return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
}
return position;
}
@@ -1768,11 +1893,15 @@ public class PrintJobConfigActivity extends Activity {
CharSequence title = null;
CharSequence subtitle = null;
- if (mPrinters.isEmpty()
- && position == DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS) {
- title = getString(R.string.searching_for_printers);
+ if (mPrinters.isEmpty()) {
+ if (position == 0) {
+ PrinterInfo printer = (PrinterInfo) getItem(position);
+ title = printer.getName();
+ } else if (position == 1) {
+ title = getString(R.string.all_printers);
+ }
} else {
- if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+ if (position == 1) {
PrinterInfo printer = (PrinterInfo) getItem(position);
title = printer.getName();
} else if (position == getCount() - 1) {
@@ -1818,6 +1947,7 @@ public class PrintJobConfigActivity extends Activity {
List<PrinterInfo> printers) {
mPrinters.clear();
mPrinters.addAll(printers);
+ ensureLastShownPrinterInPosition();
notifyDataSetChanged();
}
@@ -1827,6 +1957,27 @@ public class PrintJobConfigActivity extends Activity {
notifyDataSetInvalidated();
}
+ private void ensureLastShownPrinterInPosition() {
+ if (mLastShownPrinterId == null) {
+ return;
+ }
+ final int printerCount = mPrinters.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo printer = (PrinterInfo) mPrinters.get(i);
+ if (printer.getId().equals(mLastShownPrinterId)) {
+ // If already in the list - do nothing.
+ if (i < getCount() - 1) {
+ return;
+ }
+ // Else replace the last one.
+ final int lastPrinter = getCount() - 2;
+ mPrinters.set(i, mPrinters.get(lastPrinter - 1));
+ mPrinters.set(lastPrinter - 1, printer);
+ return;
+ }
+ }
+ }
+
private PrinterInfo createFakePdfPrinter() {
PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index fda64c9..c1f4180 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -103,8 +103,6 @@ public final class PrintSpoolerService extends Service {
private NotificationController mNotificationController;
- private PrinterDiscoverySession mDiscoverySession;
-
public static PrintSpoolerService peekInstance() {
synchronized (sLock) {
return sInstance;
@@ -225,61 +223,9 @@ public final class PrintSpoolerService extends Service {
HandlerCallerCallback.MSG_SET_CLIENT, client);
mHandlerCaller.executeOrSendMessage(message);
}
-
- @Override
- public void onPrintersAdded(List<PrinterInfo> printers) {
- Message message = mHandlerCaller.obtainMessageO(
- HandlerCallerCallback.MSG_ON_PRINTERS_ADDED, printers);
- mHandlerCaller.executeOrSendMessage(message);
- }
-
- @Override
- public void onPrintersRemoved(List<PrinterId> printerIds) {
- Message message = mHandlerCaller.obtainMessageO(
- HandlerCallerCallback.MSG_ON_PRINTERS_REMOVED, printerIds);
- mHandlerCaller.executeOrSendMessage(message);
- }
-
- @Override
- public void onPrintersUpdated(List<PrinterInfo> printers) {
- Message message = mHandlerCaller.obtainMessageO(
- HandlerCallerCallback.MSG_ON_PRINTERS_UPDATED, printers);
- mHandlerCaller.executeOrSendMessage(message);
- }
};
}
- public void createPrinterDiscoverySession() {
- Message message = mHandlerCaller.obtainMessage(
- HandlerCallerCallback.MSG_CREATE_PRINTER_DISCOVERY_SESSION);
- mHandlerCaller.executeOrSendMessage(message);
- }
-
- public void destroyPrinterDiscoverySession() {
- Message message = mHandlerCaller.obtainMessage(
- HandlerCallerCallback.MSG_DESTROY_PRINTER_DISCOVERY_SESSION);
- mHandlerCaller.executeOrSendMessage(message);
- }
-
- public void startPrinterDiscovery(List<PrinterId> priorityList) {
- Message message = mHandlerCaller.obtainMessageO(
- HandlerCallerCallback.MSG_START_PRINTER_DISCOVERY, priorityList);
- mHandlerCaller.executeOrSendMessage(message);
- }
-
- public void stopPrinterDiscovery() {
- Message message = mHandlerCaller.obtainMessage(
- HandlerCallerCallback.MSG_STOP_PRINTER_DISCOVERY);
- mHandlerCaller.executeOrSendMessage(message);
- }
-
- public void requestPrinterUpdate(PrinterId pritnerId) {
- Message message = mHandlerCaller.obtainMessageO(
- HandlerCallerCallback.MSG_REQUEST_PRINTER_UPDATE, pritnerId);
- mHandlerCaller.executeOrSendMessage(message);
- }
-
-
private void sendOnPrintJobQueued(PrintJobInfo printJob) {
Message message = mHandlerCaller.obtainMessageO(
HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob);
@@ -299,16 +245,6 @@ public final class PrintSpoolerService extends Service {
}
private final class HandlerCallerCallback implements HandlerCaller.Callback {
- public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 1;
- public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
- public static final int MSG_START_PRINTER_DISCOVERY = 3;
- public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
- public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
-
- public static final int MSG_ON_PRINTERS_ADDED = 6;
- public static final int MSG_ON_PRINTERS_REMOVED = 7;
- public static final int MSG_ON_PRINTERS_UPDATED = 8;
-
public static final int MSG_SET_CLIENT = 9;
public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 10;
public static final int MSG_ON_PRINT_JOB_QUEUED = 11;
@@ -317,81 +253,8 @@ public final class PrintSpoolerService extends Service {
public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 14;
@Override
- @SuppressWarnings("unchecked")
public void executeMessage(Message message) {
switch (message.what) {
- case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
- final IPrintSpoolerClient client;
- synchronized (mLock) {
- client = mClient;
- }
- if (client != null) {
- try {
- client.createPrinterDiscoverySession();
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error creating printer discovery session.", re);
- }
- }
- } break;
-
- case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
- final IPrintSpoolerClient client;
- synchronized (mLock) {
- client = mClient;
- }
- if (client != null) {
- try {
- client.destroyPrinterDiscoverySession();
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error destroying printer discovery session.", re);
- }
- }
- } break;
-
- case MSG_START_PRINTER_DISCOVERY: {
- final IPrintSpoolerClient client;
- synchronized (mLock) {
- client = mClient;
- }
- if (client != null) {
- List<PrinterId> priorityList = (ArrayList<PrinterId>) message.obj;
- try {
- client.startPrinterDiscovery(priorityList);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error starting printer discovery.", re);
- }
- }
- } break;
-
- case MSG_STOP_PRINTER_DISCOVERY: {
- final IPrintSpoolerClient client;
- synchronized (mLock) {
- client = mClient;
- }
- if (client != null) {
- try {
- client.stopPrinterDiscovery();
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error stopping printer discovery.", re);
- }
- }
- } break;
-
- case MSG_REQUEST_PRINTER_UPDATE: {
- final IPrintSpoolerClient client;
- synchronized (mLock) {
- client = mClient;
- }
- if (client != null) {
- PrinterId printerId = (PrinterId) message.obj;
- try {
- client.requestPrinterUpdate(printerId);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error requesing printer update.", re);
- }
- }
- } break;
-
case MSG_SET_CLIENT: {
synchronized (mLock) {
mClient = (IPrintSpoolerClient) message.obj;
@@ -452,39 +315,6 @@ public final class PrintSpoolerService extends Service {
case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
checkAllPrintJobsHandled();
} break;
-
- case MSG_ON_PRINTERS_ADDED: {
- final PrinterDiscoverySession session;
- synchronized (mLock) {
- session = mDiscoverySession;
- }
- if (session != null) {
- List<PrinterInfo> printers = (ArrayList<PrinterInfo>) message.obj;
- session.onPrintersAdded(printers);
- }
- } break;
-
- case MSG_ON_PRINTERS_REMOVED: {
- final PrinterDiscoverySession session;
- synchronized (mLock) {
- session = mDiscoverySession;
- }
- if (session != null) {
- List<PrinterId> printerIds = (ArrayList<PrinterId>) message.obj;
- session.onPrintersRemoved(printerIds);
- }
- } break;
-
- case MSG_ON_PRINTERS_UPDATED: {
- final PrinterDiscoverySession session;
- synchronized (mLock) {
- session = mDiscoverySession;
- }
- if (session != null) {
- List<PrinterInfo> printers = (ArrayList<PrinterInfo>) message.obj;
- session.onPrintersUpdated(printers);
- }
- } break;
}
}
}
@@ -583,12 +413,6 @@ public final class PrintSpoolerService extends Service {
}
}
- private void setPrinterDiscoverySessionClient(PrinterDiscoverySession session) {
- synchronized (mLock) {
- mDiscoverySession = session;
- }
- }
-
private int generatePrintJobIdLocked() {
int printJobId = sPrintJobIdCounter++;
while (isDuplicatePrintJobId(printJobId)) {
@@ -1352,46 +1176,4 @@ public final class PrintSpoolerService extends Service {
return true;
}
}
-
- public static abstract class PrinterDiscoverySession {
-
- private PrintSpoolerService mService;
-
- private boolean mIsStarted;
-
- public PrinterDiscoverySession() {
- mService = PrintSpoolerService.peekInstance();
- mService.createPrinterDiscoverySession();
- mService.setPrinterDiscoverySessionClient(this);
- }
-
- public final void startPrinterDisovery(List<PrinterId> priorityList) {
- mIsStarted = true;
- mService.startPrinterDiscovery(priorityList);
- }
-
- public final void stopPrinterDiscovery() {
- mIsStarted = false;
- mService.stopPrinterDiscovery();
- }
-
- public void requestPrinterUpdated(PrinterId printerId) {
- mService.requestPrinterUpdate(printerId);
- }
-
- public final void destroy() {
- mService.setPrinterDiscoverySessionClient(null);
- mService.destroyPrinterDiscoverySession();
- }
-
- public final boolean isStarted() {
- return mIsStarted;
- }
-
- public abstract void onPrintersAdded(List<PrinterInfo> printers);
-
- public abstract void onPrintersRemoved(List<PrinterId> printerIds);
-
- public abstract void onPrintersUpdated(List<PrinterInfo> printers);
- }
}
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index 8ee2fea..671a5dc 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -31,8 +31,10 @@ import android.os.UserHandle;
import android.print.IPrintClient;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintManager;
+import android.print.IPrinterDiscoveryObserver;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
+import android.print.PrinterId;
import android.provider.Settings;
import android.util.SparseArray;
@@ -188,6 +190,84 @@ public final class PrintManagerService extends IPrintManager.Stub {
}
}
+ @Override
+ public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
+ int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.createPrinterDiscoverySession(observer);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
+ int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.destroyPrinterDiscoverySession(observer);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
+ List<PrinterId> priorityList, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.startPrinterDiscovery(observer, priorityList);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.stopPrinterDiscovery(observer);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void requestPrinterUpdate(PrinterId printerId, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.requestPrinterUpdate(printerId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private void registerContentObservers() {
final Uri enabledPrintServicesUri = Settings.Secure.getUriFor(
Settings.Secure.ENABLED_PRINT_SERVICES);
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 5c68460..7f4b343 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -61,6 +61,8 @@ final class RemotePrintService implements DeathRecipient {
private final RemotePrintSpooler mSpooler;
+ private final UserState mUserState;
+
private final int mUserId;
private final List<Runnable> mPendingCommands = new ArrayList<Runnable>();
@@ -82,8 +84,9 @@ final class RemotePrintService implements DeathRecipient {
private boolean mHasPrinterDiscoverySession;
public RemotePrintService(Context context, ComponentName componentName, int userId,
- RemotePrintSpooler spooler) {
+ RemotePrintSpooler spooler, UserState userState) {
mContext = context;
+ mUserState = userState;
mComponentName = componentName;
mIntent = new Intent().setComponent(mComponentName);
mUserId = userId;
@@ -561,7 +564,7 @@ final class RemotePrintService implements DeathRecipient {
throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
final long identity = Binder.clearCallingIdentity();
try {
- service.mSpooler.onPrintersAdded(printers);
+ service.mUserState.onPrintersAdded(printers);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -575,7 +578,7 @@ final class RemotePrintService implements DeathRecipient {
throwIfPrinterIdsTampered(service.mComponentName, printerIds);
final long identity = Binder.clearCallingIdentity();
try {
- service.mSpooler.onPrintersRemoved(printerIds);
+ service.mUserState.onPrintersRemoved(printerIds);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -589,7 +592,7 @@ final class RemotePrintService implements DeathRecipient {
throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
final long identity = Binder.clearCallingIdentity();
try {
- service.mSpooler.onPrintersUpdated(printers);
+ service.mUserState.onPrintersUpdated(printers);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index d261288..db0eb33 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -34,8 +34,6 @@ import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
-import android.print.PrinterId;
-import android.print.PrinterInfo;
import android.util.Slog;
import android.util.TimedRemoteCaller;
@@ -93,11 +91,6 @@ final class RemotePrintSpooler {
public static interface PrintSpoolerCallbacks {
public void onPrintJobQueued(PrintJobInfo printJob);
public void onAllPrintJobsForServiceHandled(ComponentName printService);
- public void createPrinterDiscoverySession();
- public void destroyPrinterDiscoverySession();
- public void startPrinterDiscovery(List<PrinterId> priorityList);
- public void stopPrinterDiscovery();
- public void requestPrinterUpdate(PrinterId printerId);
}
public RemotePrintSpooler(Context context, int userId,
@@ -305,78 +298,6 @@ final class RemotePrintSpooler {
}
}
- public final void onPrintersAdded(List<PrinterInfo> printers) {
- throwIfCalledOnMainThread();
- synchronized (mLock) {
- throwIfDestroyedLocked();
- mCanUnbind = false;
- }
- try {
- getRemoteInstanceLazy().onPrintersAdded(printers);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error adding printers.", re);
- } catch (TimeoutException te) {
- Slog.e(LOG_TAG, "Error adding printers.", te);
- } finally {
- if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
- + "] onPrintersAdded()");
- }
- synchronized (mLock) {
- mCanUnbind = true;
- mLock.notifyAll();
- }
- }
- }
-
- public final void onPrintersRemoved(List<PrinterId> printerIds) {
- throwIfCalledOnMainThread();
- synchronized (mLock) {
- throwIfDestroyedLocked();
- mCanUnbind = false;
- }
- try {
- getRemoteInstanceLazy().onPrintersRemoved(printerIds);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error removing printers.", re);
- } catch (TimeoutException te) {
- Slog.e(LOG_TAG, "Error removing printers.", te);
- } finally {
- if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
- + "] onPrintersRemoved()");
- }
- synchronized (mLock) {
- mCanUnbind = true;
- mLock.notifyAll();
- }
- }
- }
-
- public final void onPrintersUpdated(List<PrinterInfo> printers) {
- throwIfCalledOnMainThread();
- synchronized (mLock) {
- throwIfDestroyedLocked();
- mCanUnbind = false;
- }
- try {
- getRemoteInstanceLazy().onPrintersUpdated(printers);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error updating printers.", re);
- } catch (TimeoutException te) {
- Slog.e(LOG_TAG, "Error updating printers.", te);
- } finally {
- if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
- + "] onPrintersUpdted()");
- }
- synchronized (mLock) {
- mCanUnbind = true;
- mLock.notifyAll();
- }
- }
- }
-
private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException {
synchronized (mLock) {
if (mRemoteInstance != null) {
@@ -672,70 +593,5 @@ final class RemotePrintSpooler {
}
}
}
-
- @Override
- public void createPrinterDiscoverySession() {
- RemotePrintSpooler spooler = mWeakSpooler.get();
- if (spooler != null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- spooler.mCallbacks.createPrinterDiscoverySession();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- @Override
- public void destroyPrinterDiscoverySession() {
- RemotePrintSpooler spooler = mWeakSpooler.get();
- if (spooler != null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- spooler.mCallbacks.destroyPrinterDiscoverySession();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- @Override
- public void startPrinterDiscovery(List<PrinterId> priorityList) {
- RemotePrintSpooler spooler = mWeakSpooler.get();
- if (spooler != null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- spooler.mCallbacks.startPrinterDiscovery(priorityList);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- @Override
- public void stopPrinterDiscovery() {
- RemotePrintSpooler spooler = mWeakSpooler.get();
- if (spooler != null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- spooler.mCallbacks.stopPrinterDiscovery();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- @Override
- public void requestPrinterUpdate(PrinterId printerId) {
- RemotePrintSpooler spooler = mWeakSpooler.get();
- if (spooler != null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- spooler.mCallbacks.requestPrinterUpdate(printerId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
}
}
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index 9d7cfdd..c979a11 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -21,14 +21,26 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.print.IPrinterDiscoveryObserver;
import android.print.PrintJobInfo;
import android.print.PrinterId;
+import android.print.PrinterInfo;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
+import android.util.ArrayMap;
+import android.util.Log;
import android.util.Slog;
+import com.android.internal.os.SomeArgs;
import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
import java.util.ArrayList;
@@ -45,6 +57,10 @@ final class UserState implements PrintSpoolerCallbacks {
private static final String LOG_TAG = "UserState";
+ private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
+
+ private static final int MAX_ITEMS_PER_CALLBACK = 100;
+
private static final char COMPONENT_NAME_SEPARATOR = ':';
private final SimpleStringSplitter mStringColonSplitter =
@@ -70,6 +86,8 @@ final class UserState implements PrintSpoolerCallbacks {
private final RemotePrintSpooler mSpooler;
+ private PrinterDiscoverySessionMediator mPrinterDiscoverySession;
+
private boolean mDestroyed;
public UserState(Context context, int userId, Object lock) {
@@ -104,86 +122,135 @@ final class UserState implements PrintSpoolerCallbacks {
}
}
- @Override
- public void createPrinterDiscoverySession() {
- final List<RemotePrintService> services;
+ public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer) {
synchronized (mLock) {
throwIfDestroyedLocked();
if (mActiveServices.isEmpty()) {
return;
}
- services = new ArrayList<RemotePrintService>(mActiveServices.values());
+ if (mPrinterDiscoverySession == null) {
+ // If we do not have a session, tell all service to create one.
+ mPrinterDiscoverySession = new PrinterDiscoverySessionMediator(mContext) {
+ @Override
+ public void onDestroyed() {
+ mPrinterDiscoverySession = null;
+ }
+ };
+ // Add the observer to the brand new session.
+ mPrinterDiscoverySession.addObserverLocked(observer);
+ } else {
+ // If services have created session, just add the observer.
+ mPrinterDiscoverySession.addObserverLocked(observer);
+ }
}
- final int serviceCount = services.size();
- for (int i = 0; i < serviceCount; i++) {
- RemotePrintService service = services.get(i);
- service.createPrinterDiscoverySession();
+ }
+
+ public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer) {
+ synchronized (mLock) {
+ // Already destroyed - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Remove this observer.
+ mPrinterDiscoverySession.removeObserverLocked(observer);
}
}
- @Override
- public void destroyPrinterDiscoverySession() {
- final List<RemotePrintService> services;
+ public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
+ List<PrinterId> printerIds) {
synchronized (mLock) {
throwIfDestroyedLocked();
+ // No services - nothing to do.
if (mActiveServices.isEmpty()) {
return;
}
- services = new ArrayList<RemotePrintService>(mActiveServices.values());
- }
- final int serviceCount = services.size();
- for (int i = 0; i < serviceCount; i++) {
- RemotePrintService service = services.get(i);
- service.destroyPrinterDiscoverySession();
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Kick of discovery.
+ mPrinterDiscoverySession.startPrinterDiscoveryLocked(observer,
+ printerIds);
}
}
- @Override
- public void startPrinterDiscovery(List<PrinterId> printerIds) {
- final List<RemotePrintService> services;
+ public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer) {
synchronized (mLock) {
throwIfDestroyedLocked();
+ // No services - nothing to do.
if (mActiveServices.isEmpty()) {
return;
}
- services = new ArrayList<RemotePrintService>(mActiveServices.values());
- }
- final int serviceCount = services.size();
- for (int i = 0; i < serviceCount; i++) {
- RemotePrintService service = services.get(i);
- service.startPrinterDiscovery(printerIds);
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Kick of discovery.
+ mPrinterDiscoverySession.stopPrinterDiscoveryLocked(observer);
}
}
- @Override
- public void stopPrinterDiscovery() {
- final List<RemotePrintService> services;
+ public void requestPrinterUpdate(PrinterId printerId) {
synchronized (mLock) {
throwIfDestroyedLocked();
+ // No services - nothing to do.
if (mActiveServices.isEmpty()) {
return;
}
- services = new ArrayList<RemotePrintService>(mActiveServices.values());
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request an updated.
+ mPrinterDiscoverySession.requestPrinterUpdateLocked(printerId);
}
- final int serviceCount = services.size();
- for (int i = 0; i < serviceCount; i++) {
- RemotePrintService service = services.get(i);
- service.stopPrinterDiscovery();
+ }
+
+ public void onPrintersAdded(List<PrinterInfo> printers) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ // No services - nothing to do.
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request an updated.
+ mPrinterDiscoverySession.onPrintersAddedLocked(printers);
}
}
- @Override
- public void requestPrinterUpdate(PrinterId printerId) {
- final RemotePrintService service;
+ public void onPrintersRemoved(List<PrinterId> printerIds) {
synchronized (mLock) {
throwIfDestroyedLocked();
+ // No services - nothing to do.
if (mActiveServices.isEmpty()) {
return;
}
- service = mActiveServices.get(printerId.getServiceName());
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request an updated.
+ mPrinterDiscoverySession.onPrintersRemovedLocked(printerIds);
}
- if (service != null) {
- service.requestPrinterUpdate(printerId);
+ }
+
+ public void onPrintersUpdated(List<PrinterInfo> printers) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ // No services - nothing to do.
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request an updated.
+ mPrinterDiscoverySession.onPrintersUpdatedLocked(printers);
}
}
@@ -222,6 +289,10 @@ final class UserState implements PrintSpoolerCallbacks {
mActiveServices.clear();
mInstalledServices.clear();
mEnabledServices.clear();
+ if (mPrinterDiscoverySession != null) {
+ mPrinterDiscoverySession.destroyLocked();
+ mPrinterDiscoverySession = null;
+ }
mDestroyed = true;
}
@@ -302,13 +373,20 @@ final class UserState implements PrintSpoolerCallbacks {
resolveInfo.serviceInfo.name);
if (mEnabledServices.contains(serviceName)) {
if (!mActiveServices.containsKey(serviceName)) {
- mActiveServices.put(serviceName, new RemotePrintService(
- mContext, serviceName, mUserId, mSpooler));
+ RemotePrintService service = new RemotePrintService(
+ mContext, serviceName, mUserId, mSpooler, this);
+ mActiveServices.put(serviceName, service);
+ if (mPrinterDiscoverySession != null) {
+ mPrinterDiscoverySession.onServiceAddedLocked(service);
+ }
}
} else {
RemotePrintService service = mActiveServices.remove(serviceName);
if (service != null) {
service.destroy();
+ if (mPrinterDiscoverySession != null) {
+ mPrinterDiscoverySession.onServiceRemovedLocked(serviceName);
+ }
}
}
}
@@ -319,5 +397,496 @@ final class UserState implements PrintSpoolerCallbacks {
throw new IllegalStateException("Cannot interact with a destroyed instance.");
}
}
-}
+ private class PrinterDiscoverySessionMediator {
+ private final ArrayMap<PrinterId, PrinterInfo> mPrinters =
+ new ArrayMap<PrinterId, PrinterInfo>();
+
+ private final RemoteCallbackList<IPrinterDiscoveryObserver> mDiscoveryObservers =
+ new RemoteCallbackList<IPrinterDiscoveryObserver>() {
+ @Override
+ public void onCallbackDied(IPrinterDiscoveryObserver observer) {
+ synchronized (mLock) {
+ stopPrinterDiscoveryLocked(observer);
+ removeObserverLocked(observer);
+ }
+ }
+ };
+
+ private final List<IBinder> mStartedPrinterDiscoveryTokens = new ArrayList<IBinder>();
+
+ private final Handler mHandler;
+
+ private boolean mIsDestroyed;
+
+ public PrinterDiscoverySessionMediator(Context context) {
+ mHandler = new SessionHandler(context.getMainLooper());
+ // Kick off the session creation.
+ List<RemotePrintService> services = new ArrayList<RemotePrintService>(
+ mActiveServices.values());
+ mHandler.obtainMessage(SessionHandler
+ .MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION, services)
+ .sendToTarget();
+ }
+
+ public void addObserverLocked(IPrinterDiscoveryObserver observer) {
+ // Add the observer.
+ mDiscoveryObservers.register(observer);
+
+ // Bring the added observer up to speed with the printers.
+ if (!mPrinters.isEmpty()) {
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>(mPrinters.values());
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = observer;
+ args.arg2 = printers;
+ mHandler.obtainMessage(SessionHandler.MSG_PRINTERS_ADDED,
+ args).sendToTarget();
+ }
+ }
+
+ public void removeObserverLocked(IPrinterDiscoveryObserver observer) {
+ // Remove the observer.
+ mDiscoveryObservers.unregister(observer);
+ // No one else observing - then kill it.
+ if (mDiscoveryObservers.getRegisteredCallbackCount() == 0) {
+ destroyLocked();
+ }
+ }
+
+ public final void startPrinterDiscoveryLocked(IPrinterDiscoveryObserver observer,
+ List<PrinterId> priorityList) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not starting dicovery - session destroyed");
+ return;
+ }
+
+ // If printer discovery is ongoing and the start request has a list
+ // of printer to be checked, then we just request refreshing each of
+ // them rather making another start discovery request.
+ if (!mStartedPrinterDiscoveryTokens.isEmpty()
+ && priorityList != null && !priorityList.isEmpty()) {
+ final int priorityIdCount = priorityList.size();
+ for (int i = 0; i < priorityIdCount; i++) {
+ requestPrinterUpdate(priorityList.get(i));
+ }
+ return;
+ }
+
+ // Remember we got a start request to match with an end.
+ mStartedPrinterDiscoveryTokens.add(observer.asBinder());
+ // The service are already performing discovery - nothing to do.
+ if (mStartedPrinterDiscoveryTokens.size() > 1) {
+ return;
+ }
+ List<RemotePrintService> services = new ArrayList<RemotePrintService>(
+ mActiveServices.values());
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = services;
+ args.arg2 = priorityList;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_DISPATCH_START_PRINTER_DISCOVERY, args)
+ .sendToTarget();
+ }
+
+ public final void stopPrinterDiscoveryLocked(IPrinterDiscoveryObserver observer) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not stopping dicovery - session destroyed");
+ return;
+ }
+ // This one did not make an active discovery request - nothing to do.
+ if (!mStartedPrinterDiscoveryTokens.remove(observer.asBinder())) {
+ return;
+ }
+ // There are other interested observers - do not stop discovery.
+ if (!mStartedPrinterDiscoveryTokens.isEmpty()) {
+ return;
+ }
+ List<RemotePrintService> services = new ArrayList<RemotePrintService>(
+ mActiveServices.values());
+ mHandler.obtainMessage(SessionHandler
+ .MSG_DISPATCH_STOP_PRINTER_DISCOVERY, services)
+ .sendToTarget();
+ }
+
+ public void requestPrinterUpdateLocked(PrinterId printerId) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not updating pritner - session destroyed");
+ return;
+ }
+ RemotePrintService service = mActiveServices.get(printerId.getServiceName());
+ if (service != null) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = service;
+ args.arg2 = printerId;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_REQUEST_PRINTER_UPDATE, args)
+ .sendToTarget();
+ }
+ }
+
+ public void onDestroyed() {
+ /* do nothing */
+ }
+
+ public void destroyLocked() {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not destroying - session destroyed");
+ return;
+ }
+ // Make sure discovery is stopped.
+ final int observerCount = mStartedPrinterDiscoveryTokens.size();
+ for (int i = 0; i < observerCount; i++) {
+ IBinder token = mStartedPrinterDiscoveryTokens.get(i);
+ stopPrinterDiscoveryLocked(IPrinterDiscoveryObserver.Stub.asInterface(token));
+ }
+ // Tell the services we are done.
+ List<RemotePrintService> services = new ArrayList<RemotePrintService>(
+ mActiveServices.values());
+ mHandler.obtainMessage(SessionHandler
+ .MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION, services)
+ .sendToTarget();
+ }
+
+ public void onPrintersAddedLocked(List<PrinterInfo> printers) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onPrintersAddedLocked()");
+ }
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not adding printers - session destroyed");
+ return;
+ }
+ List<PrinterInfo> addedPrinters = null;
+ final int addedPrinterCount = printers.size();
+ for (int i = 0; i < addedPrinterCount; i++) {
+ PrinterInfo printer = printers.get(i);
+ if (!mPrinters.containsKey(printer.getId())) {
+ mPrinters.put(printer.getId(), printer);
+ if (addedPrinters == null) {
+ addedPrinters = new ArrayList<PrinterInfo>();
+ }
+ addedPrinters.add(printer);
+ }
+ }
+ if (addedPrinters != null) {
+ mHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_ADDED,
+ addedPrinters).sendToTarget();
+ }
+ }
+
+ public void onPrintersRemovedLocked(List<PrinterId> printerIds) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onPrintersRemovedLocked()");
+ }
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not removing printers - session destroyed");
+ return;
+ }
+ List<PrinterId> removedPrinterIds = null;
+ final int removedPrinterCount = printerIds.size();
+ for (int i = 0; i < removedPrinterCount; i++) {
+ PrinterId removedPrinterId = printerIds.get(i);
+ if (mPrinters.remove(removedPrinterId) != null) {
+ if (removedPrinterIds == null) {
+ removedPrinterIds = new ArrayList<PrinterId>();
+ }
+ removedPrinterIds.add(removedPrinterId);
+ }
+ }
+ if (removedPrinterIds != null) {
+ mHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
+ removedPrinterIds).sendToTarget();
+ }
+ }
+
+ public void onPrintersUpdatedLocked(List<PrinterInfo> printers) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onPrintersUpdatedLocked()");
+ }
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not updating printers - session destroyed");
+ return;
+ }
+ List<PrinterInfo> updatedPrinters = null;
+ final int updatedPrinterCount = printers.size();
+ for (int i = 0; i < updatedPrinterCount; i++) {
+ PrinterInfo updatedPrinter = printers.get(i);
+ if (mPrinters.containsKey(updatedPrinter.getId())) {
+ mPrinters.put(updatedPrinter.getId(), updatedPrinter);
+ if (updatedPrinters == null) {
+ updatedPrinters = new ArrayList<PrinterInfo>();
+ }
+ updatedPrinters.add(updatedPrinter);
+ }
+ }
+ if (updatedPrinters != null) {
+ mHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_UPDATED,
+ updatedPrinters).sendToTarget();
+ }
+ }
+
+ public void onServiceRemovedLocked(ComponentName serviceName) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not updating removed service - session destroyed");
+ return;
+ }
+ // No printers - nothing to do.
+ if (mPrinters.isEmpty()) {
+ return;
+ }
+ // Remove the printers for that service.
+ List<PrinterInfo> removedPrinters = null;
+ final int printerCount = mPrinters.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo printer = mPrinters.get(i);
+ if (printer.getId().getServiceName().equals(serviceName)) {
+ if (removedPrinters == null) {
+ removedPrinters = new ArrayList<PrinterInfo>();
+ }
+ removedPrinters.add(printer);
+ }
+ }
+ if (!removedPrinters.isEmpty()) {
+ mHandler.obtainMessage(
+ SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
+ removedPrinters).sendToTarget();
+ }
+ }
+
+ public void onServiceAddedLocked(RemotePrintService service) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not updating added service - session destroyed");
+ return;
+ }
+ // Tell the service to create a session.
+ mHandler.obtainMessage(
+ SessionHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
+ service).sendToTarget();
+ // If there are some observers that started discovery - tell the service.
+ if (mDiscoveryObservers.getRegisteredCallbackCount() > 0) {
+ mHandler.obtainMessage(
+ SessionHandler.MSG_START_PRINTER_DISCOVERY,
+ service).sendToTarget();
+ }
+ }
+
+ private void handleDispatchPrintersAdded(List<PrinterInfo> addedPrinters) {
+ final int observerCount = mDiscoveryObservers.beginBroadcast();
+ for (int i = 0; i < observerCount; i++) {
+ IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
+ try {
+ observer.onPrintersAdded(addedPrinters);
+ } catch (RemoteException re) {
+ Log.i(LOG_TAG, "Error dispatching added printers", re);
+ }
+ }
+ mDiscoveryObservers.finishBroadcast();
+ }
+
+ private void handleDispatchPrintersRemoved(List<PrinterId> removedPrinterIds) {
+ final int observerCount = mDiscoveryObservers.beginBroadcast();
+ for (int i = 0; i < observerCount; i++) {
+ IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
+ try {
+ observer.onPrintersRemoved(removedPrinterIds);
+ } catch (RemoteException re) {
+ Log.i(LOG_TAG, "Error dispatching removed printers", re);
+ }
+ }
+ mDiscoveryObservers.finishBroadcast();
+ }
+
+ private void handleDispatchPrintersUpdated(List<PrinterInfo> updatedPrinters) {
+ final int observerCount = mDiscoveryObservers.beginBroadcast();
+ for (int i = 0; i < observerCount; i++) {
+ IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
+ try {
+ observer.onPrintersUpdated(updatedPrinters);
+ } catch (RemoteException re) {
+ Log.i(LOG_TAG, "Error dispatching updated printers", re);
+ }
+ }
+ mDiscoveryObservers.finishBroadcast();
+ }
+
+ private void handleDispatchCreatePrinterDiscoverySession(
+ List<RemotePrintService> services) {
+ final int serviceCount = services.size();
+ for (int i = 0; i < serviceCount; i++) {
+ RemotePrintService service = services.get(i);
+ service.createPrinterDiscoverySession();
+ }
+ }
+
+ private void handleDispatchDestroyPrinterDiscoverySession(
+ List<RemotePrintService> services) {
+ final int serviceCount = services.size();
+ for (int i = 0; i < serviceCount; i++) {
+ RemotePrintService service = services.get(i);
+ service.destroyPrinterDiscoverySession();
+ }
+ onDestroyed();
+ }
+
+ private void handleDispatchStartPrinterDiscovery(
+ List<RemotePrintService> services, List<PrinterId> printerIds) {
+ final int serviceCount = services.size();
+ for (int i = 0; i < serviceCount; i++) {
+ RemotePrintService service = services.get(i);
+ service.startPrinterDiscovery(printerIds);
+ }
+ }
+
+ private void handleDispatchStopPrinterDiscovery(List<RemotePrintService> services) {
+ final int serviceCount = services.size();
+ for (int i = 0; i < serviceCount; i++) {
+ RemotePrintService service = services.get(i);
+ service.stopPrinterDiscovery();
+ }
+ }
+
+ private void handleRequestPrinterUpdate(RemotePrintService service,
+ PrinterId printerId) {
+ service.requestPrinterUpdate(printerId);
+ }
+
+ private void handlePrintersAdded(IPrinterDiscoveryObserver observer,
+ List<PrinterInfo> printers) {
+ try {
+ final int printerCount = printers.size();
+ if (printerCount <= MAX_ITEMS_PER_CALLBACK) {
+ observer.onPrintersAdded(printers);
+ } else {
+ // Send the added printers in chunks avoiding the binder transaction limit.
+ final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1;
+ for (int i = 0; i < transactionCount; i++) {
+ final int start = i * MAX_ITEMS_PER_CALLBACK;
+ final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount);
+ List<PrinterInfo> subPrinters = printers.subList(start, end);
+ observer.onPrintersAdded(subPrinters);
+ }
+ }
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error sending added printers", re);
+ }
+ }
+
+ private void handlePrintersRemoved(IPrinterDiscoveryObserver observer,
+ List<PrinterId> printerIds) {
+ try {
+ final int printerCount = printerIds.size();
+ if (printerCount <= MAX_ITEMS_PER_CALLBACK) {
+ observer.onPrintersRemoved(printerIds);
+ } else {
+ // Send the added printers in chunks avoiding the binder transaction limit.
+ final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1;
+ for (int i = 0; i < transactionCount; i++) {
+ final int start = i * MAX_ITEMS_PER_CALLBACK;
+ final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount);
+ List<PrinterId> subPrinterIds = printerIds.subList(start, end);
+ observer.onPrintersRemoved(subPrinterIds);
+ }
+ }
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error sending added printers", re);
+ }
+ }
+
+ private final class SessionHandler extends Handler {
+ public static final int MSG_PRINTERS_ADDED = 1;
+ public static final int MSG_PRINTERS_REMOVED = 2;
+ public static final int MSG_DISPATCH_PRINTERS_ADDED = 3;
+ public static final int MSG_DISPATCH_PRINTERS_REMOVED = 4;
+ public static final int MSG_DISPATCH_PRINTERS_UPDATED = 5;
+
+ public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 6;
+ public static final int MSG_START_PRINTER_DISCOVERY = 7;
+ public static final int MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION = 8;
+ public static final int MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION = 9;
+ public static final int MSG_DISPATCH_START_PRINTER_DISCOVERY = 10;
+ public static final int MSG_DISPATCH_STOP_PRINTER_DISCOVERY = 11;
+ public static final int MSG_REQUEST_PRINTER_UPDATE = 12;
+
+ SessionHandler(Looper looper) {
+ super(looper, null, false);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MSG_PRINTERS_ADDED: {
+ SomeArgs args = (SomeArgs) message.obj;
+ IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg1;
+ List<PrinterInfo> addedPrinters = (List<PrinterInfo>) args.arg2;
+ args.recycle();
+ handlePrintersAdded(observer, addedPrinters);
+ } break;
+
+ case MSG_PRINTERS_REMOVED: {
+ SomeArgs args = (SomeArgs) message.obj;
+ IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg1;
+ List<PrinterId> removedPrinterIds = (List<PrinterId>) args.arg2;
+ args.recycle();
+ handlePrintersRemoved(observer, removedPrinterIds);
+ }
+
+ case MSG_DISPATCH_PRINTERS_ADDED: {
+ List<PrinterInfo> addedPrinters = (List<PrinterInfo>) message.obj;
+ handleDispatchPrintersAdded(addedPrinters);
+ } break;
+
+ case MSG_DISPATCH_PRINTERS_REMOVED: {
+ List<PrinterId> removedPrinterIds = (List<PrinterId>) message.obj;
+ handleDispatchPrintersRemoved(removedPrinterIds);
+ } break;
+
+ case MSG_DISPATCH_PRINTERS_UPDATED: {
+ List<PrinterInfo> updatedPrinters = (List<PrinterInfo>) message.obj;
+ handleDispatchPrintersUpdated(updatedPrinters);
+ } break;
+
+ case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
+ RemotePrintService service = (RemotePrintService) message.obj;
+ service.createPrinterDiscoverySession();
+ } break;
+
+ case MSG_START_PRINTER_DISCOVERY: {
+ RemotePrintService service = (RemotePrintService) message.obj;
+ service.startPrinterDiscovery(null);
+ } break;
+
+ case MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION: {
+ List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
+ handleDispatchCreatePrinterDiscoverySession(services);
+ } break;
+
+ case MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION: {
+ List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
+ handleDispatchDestroyPrinterDiscoverySession(services);
+ } break;
+
+ case MSG_DISPATCH_START_PRINTER_DISCOVERY: {
+ SomeArgs args = (SomeArgs) message.obj;
+ List<RemotePrintService> services = (List<RemotePrintService>) args.arg1;
+ List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
+ args.recycle();
+ handleDispatchStartPrinterDiscovery(services, printerIds);
+ } break;
+
+ case MSG_DISPATCH_STOP_PRINTER_DISCOVERY: {
+ List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
+ handleDispatchStopPrinterDiscovery(services);
+ } break;
+
+ case MSG_REQUEST_PRINTER_UPDATE: {
+ SomeArgs args = (SomeArgs) message.obj;
+ RemotePrintService service = (RemotePrintService) args.arg1;
+ PrinterId printerId = (PrinterId) args.arg2;
+ args.recycle();
+ handleRequestPrinterUpdate(service, printerId);
+ } break;
+ }
+ }
+ }
+ }
+} \ No newline at end of file