summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/print/PrintAttributes.java16
-rw-r--r--packages/PrintSpooler/res/layout/print_job_config_activity.xml441
-rw-r--r--packages/PrintSpooler/res/values/constants.xml4
-rw-r--r--packages/PrintSpooler/res/values/strings.xml10
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java1118
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java153
6 files changed, 1081 insertions, 661 deletions
diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java
index 65f1330..87d75c0 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -384,6 +384,22 @@ public final class PrintAttributes implements Parcelable {
}
/**
+ * @hide
+ */
+ public void copyFrom(PrintAttributes other) {
+ mMediaSize = other.mMediaSize;
+ mResolution = other.mResolution;
+ mMargins = other.mMargins;
+ mInputTray = other.mInputTray;
+ mOutputTray = other.mOutputTray;
+ mDuplexMode = other.mDuplexMode;
+ mColorMode = other.mColorMode;
+ mFittingMode = other.mFittingMode;
+ mOrientation = other.mOrientation;
+ mCopies = other.mCopies;
+ }
+
+ /**
* This class specifies a supported media size.
*/
public static final class MediaSize {
diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity.xml b/packages/PrintSpooler/res/layout/print_job_config_activity.xml
index 8736bdd..32bc15a 100644
--- a/packages/PrintSpooler/res/layout/print_job_config_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_job_config_activity.xml
@@ -5,7 +5,7 @@
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
+ 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,
@@ -14,197 +14,264 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:scrollbars="vertical">
- <ScrollView
- android:layout_width="fill_parent"
+ <GridLayout
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@*android:color/bright_foreground_disabled_holo_light">
+ android:orientation="vertical"
+ 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_marginLeft="32dip"
+ android:layout_marginRight="32dip"
+ android:layout_marginBottom="12dip"
+ 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_marginLeft="32dip"
+ android:layout_marginRight="12dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="2"
+ android:layout_column="0"
+ android:layout_gravity="bottom"
+ android:inputType="numberDecimal"
+ android:selectAllOnFocus="true"
+ android:minWidth="150dip">
+ </view>
+
+ <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_margin="32dip"
- 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_marginBottom="12dip"
- android:layout_row="0"
- android:layout_column="0"
- android:layout_columnSpan="2"
- android:minWidth="324dip"
- 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_marginRight="12dip"
- android:layout_marginBottom="12dip"
- android:layout_row="2"
- android:layout_column="0"
- android:layout_gravity="bottom"
- android:inputType="numberDecimal"
- android:selectAllOnFocus="true"
- android:minWidth="150dip">
- </view>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="1"
- android:layout_column="0"
- android:layout_gravity="left|bottom"
- android:text="@string/label_copies"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- android:labelFor="@id/copies_edittext">
- </TextView>
-
- <!-- Paper size -->
-
- <Spinner
- android:id="@+id/paper_size_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginBottom="12dip"
- android:layout_row="2"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginTop="12dip"
- android:layout_row="1"
- android:layout_column="1"
- android:text="@string/label_paper_size"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- android:labelFor="@id/paper_size_spinner">
- </TextView>
-
- <!-- Color -->
-
- <Spinner
- android:id="@+id/color_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginRight="12dip"
- android:layout_marginBottom="12dip"
- android:layout_row="4"
- android:layout_column="0"
- android:minWidth="150dip">
- </Spinner>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="3"
- android:layout_column="0"
- android:text="@string/label_color"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- android:labelFor="@id/color_spinner">
- </TextView>
-
- <!-- Orientation -->
-
- <Spinner
- android:id="@+id/orientation_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginBottom="12dip"
- android:layout_row="4"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginTop="12dip"
- android:layout_row="3"
- android:layout_column="1"
- android:text="@string/label_orientation"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- android:labelFor="@id/orientation_spinner">
- </TextView>
-
- <!-- Pages -->
-
- <Spinner
- android:id="@+id/range_options_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginRight="12dip"
- android:layout_row="6"
- android:layout_column="0"
- android:minWidth="150dip">
- </Spinner>
-
- <EditText
- android:id="@+id/page_range_edittext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- 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">
- </EditText>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="5"
- android:layout_column="0"
- android:text="@string/label_pages"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- android:labelFor="@id/range_options_spinner">
- </TextView>
-
- </GridLayout>
-
- </ScrollView>
-
- <Button
- android:id="@+id/print_button"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="0dip"
- android:text="@string/print_button"
- android:background="?android:attr/selectableItemBackground">
- </Button>
+ android:layout_marginLeft="32dip"
+ android:layout_marginTop="12dip"
+ android:layout_marginRight="12dip"
+ android:layout_row="1"
+ android:layout_column="0"
+ android:layout_gravity="left|bottom"
+ android:text="@string/label_copies"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/copies_edittext">
+ </TextView>
+
+ <!-- Paper size -->
+
+ <Spinner
+ android:id="@+id/paper_size_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginRight="32dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="2"
+ android:layout_column="1"
+ android:minWidth="150dip">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginRight="32dip"
+ android:layout_marginTop="12dip"
+ android:layout_row="1"
+ android:layout_column="1"
+ android:text="@string/label_paper_size"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/paper_size_spinner">
+ </TextView>
+
+ <!-- Color -->
+
+ <Spinner
+ android:id="@+id/color_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="32dip"
+ android:layout_marginRight="12dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="4"
+ android:layout_column="0"
+ android:minWidth="150dip">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="32dip"
+ android:layout_marginTop="12dip"
+ android:layout_marginRight="12dip"
+ android:layout_row="3"
+ android:layout_column="0"
+ android:text="@string/label_color"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/color_spinner">
+ </TextView>
+
+ <!-- Orientation -->
+
+ <Spinner
+ android:id="@+id/orientation_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginRight="32dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="4"
+ android:layout_column="1"
+ android:minWidth="150dip">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginTop="12dip"
+ android:layout_marginRight="32dip"
+ android:layout_row="3"
+ android:layout_column="1"
+ android:text="@string/label_orientation"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/orientation_spinner">
+ </TextView>
+
+ <!-- Pages -->
+
+ <Spinner
+ android:id="@+id/range_options_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="32dip"
+ android:layout_marginRight="12dip"
+ android:layout_row="6"
+ android:layout_column="0"
+ android:minWidth="150dip">
+ </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_marginLeft="12dip"
+ android:layout_marginRight="32dip"
+ 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">
+ </view>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="32dip"
+ android:layout_marginTop="12dip"
+ android:layout_marginRight="12dip"
+ android:layout_row="5"
+ android:layout_column="0"
+ android:text="@string/label_pages"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/range_options_spinner">
+ </TextView>
+
+ <!-- Print pereview -->
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="fill_horizontal"
+ android:layout_marginLeft="32dip"
+ android:layout_marginTop="32dip"
+ android:layout_marginRight="32dip"
+ android:layout_row="7"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:background="?android:attr/listDivider"
+ android:contentDescription="@null">
+ </ImageView>
+
+ <Button
+ android:id="@+id/print_preview_button"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="fill_horizontal"
+ android:layout_marginLeft="32dip"
+ android:layout_marginRight="32dip"
+ android:layout_row="8"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:text="@string/print_preview"
+ android:gravity="left|center_vertical"
+ android:background="?android:attr/selectableItemBackground">
+ </Button>
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="fill_horizontal"
+ android:layout_marginLeft="32dip"
+ android:layout_marginRight="32dip"
+ android:layout_marginBottom="32dip"
+ android:layout_row="9"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:background="?android:attr/listDivider"
+ android:contentDescription="@null">
+ </ImageView>
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="fill_horizontal"
+ android:layout_row="10"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:background="?android:attr/listDivider"
+ android:contentDescription="@null">
+ </ImageView>
+
+ <Button
+ android:id="@+id/print_button"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="fill_horizontal"
+ android:layout_row="11"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:padding="0dip"
+ android:text="@string/print_button"
+ android:background="?android:attr/selectableItemBackground">
+ </Button>
+
+ </GridLayout>
-</LinearLayout>
+</ScrollView>
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index 7d2cdc3..96cdeb1 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -16,8 +16,8 @@
<resources>
- <integer name="page_option_value_all">1</integer>
- <integer name="page_option_value_page_range">2</integer>
+ <integer name="page_option_value_all">0</integer>
+ <integer name="page_option_value_page_range">1</integer>
<integer-array name="page_options_values" translatable="false">
<item>@integer/page_option_value_all</item>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index de6fb60..27540d7 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -43,8 +43,14 @@
<!-- 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>
- <!-- Message to notify the user of entering invalid input. [CHAR LIMIT=25] -->
- <string name="invalid_input">Invalid input</string>
+ <!-- Title for the pring preview button .[CHAR LIMIT=30] -->
+ <string name="print_preview">Print preview</string>
+
+ <!-- Title for the pring preview button if there is no PDF viewer isntalled. [CHAR LIMIT=50] -->
+ <string name="install_for_print_preview">Install PDF viewer for preview</string>
+
+ <!-- Title of the message that the printing application crashed. [CHAR LIMIT=50] -->
+ <string name="printing_app_crashed">Printing app crashed</string>
<!-- Color mode labels. -->
<string-array name="color_mode_labels">
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 19f545d..1e1cc24 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -23,6 +23,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@@ -50,6 +51,7 @@ import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.Choreographer;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@@ -95,12 +97,18 @@ public class PrintJobConfigActivity extends Activity {
private final PrintSpooler mPrintSpooler = PrintSpooler.getInstance(this);
+ private Handler mHandler;
+
+ private Editor mEditor;
+
private IPrinterDiscoveryObserver mPrinterDiscoveryObserver;
private int mAppId;
private int mPrintJobId;
- private PrintAttributes mPrintAttributes;
+ private final PrintAttributes mOldPrintAttributes = new PrintAttributes.Builder().create();
+ private final PrintAttributes mCurrPrintAttributes = new PrintAttributes.Builder().create();
+ private final PrintAttributes mTempPrintAttributes = new PrintAttributes.Builder().create();
private RemotePrintDocumentAdapter mRemotePrintAdapter;
@@ -112,152 +120,6 @@ public class PrintJobConfigActivity extends Activity {
private PrintDocumentInfo mPrintDocumentInfo;
- // UI elements
-
- private EditText mCopiesEditText;
-
- private EditText mRangeEditText;
-
- private Spinner mDestinationSpinner;
- public ArrayAdapter<SpinnerItem<PrinterInfo>> mDestinationSpinnerAdapter;
-
- private Spinner mMediaSizeSpinner;
- public ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
-
- private Spinner mColorModeSpinner;
- public ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
-
- private Spinner mOrientationSpinner;
- public ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
-
- private Spinner mRangeOptionsSpinner;
- public ArrayAdapter<SpinnerItem<Integer>> mRangeOptionsSpinnerAdapter;
-
- private Button mPrintButton;
-
- // TODO: Implement store/restore state.
-
- private final OnItemSelectedListener mOnItemSelectedListener =
- new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> spinner, View view, int position, long id) {
- if (spinner == mDestinationSpinner) {
- updateUi();
- notifyPrintableStartIfNeeded();
- } else if (spinner == mMediaSizeSpinner) {
- SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(position);
- mPrintAttributes.setMediaSize(mediaItem.value);
- updatePrintableContentIfNeeded();
- } else if (spinner == mColorModeSpinner) {
- SpinnerItem<Integer> colorModeItem =
- mColorModeSpinnerAdapter.getItem(position);
- mPrintAttributes.setColorMode(colorModeItem.value);
- } else if (spinner == mOrientationSpinner) {
- SpinnerItem<Integer> orientationItem =
- mOrientationSpinnerAdapter.getItem(position);
- mPrintAttributes.setOrientation(orientationItem.value);
- } else if (spinner == mRangeOptionsSpinner) {
- SpinnerItem<Integer> rangeOptionItem =
- mRangeOptionsSpinnerAdapter.getItem(position);
- if (rangeOptionItem.value == getResources().getInteger(
- R.integer.page_option_value_all)) {
- mRangeEditText.setVisibility(View.INVISIBLE);
- mRangeEditText.setEnabled(false);
- mRangeEditText.setText(null);
- mRangeEditText.setError(null);
- mPrintButton.setEnabled(true);
- } else if (rangeOptionItem.value == getResources().getInteger(
- R.integer.page_option_value_page_range)) {
- mRangeEditText.setVisibility(View.VISIBLE);
- mRangeEditText.setEnabled(true);
- mRangeEditText.requestFocus();
- mRangeEditText.setError(getString(R.string.invalid_input));
- InputMethodManager imm = (InputMethodManager)
- getSystemService(INPUT_METHOD_SERVICE);
- imm.showSoftInput(mRangeEditText, 0);
- }
- }
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- /* do nothing*/
- }
- };
-
- private final TextWatcher mCopiesTextWatcher = new TextWatcher() {
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- /* do nothing */
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- /* do nothing */
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
- if (editable.length() == 0) {
- mCopiesEditText.setError(getString(R.string.invalid_input));
- mPrintButton.setEnabled(false);
- return;
- }
- final int copies = Integer.parseInt(editable.toString());
- if (copies < MIN_COPIES) {
- mCopiesEditText.setError(getString(R.string.invalid_input));
- mPrintButton.setEnabled(false);
- return;
- }
- mPrintAttributes.setCopies(copies);
- mPrintButton.setEnabled(true);
- }
- };
-
- private final TextWatcher mRangeTextWatcher = new TextWatcher() {
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- /* do nothing */
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- /* do nothing */
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
- String text = editable.toString();
-
- if (TextUtils.isEmpty(text)) {
- mRangeEditText.setError(getString(R.string.invalid_input));
- mPrintButton.setEnabled(false);
- return;
- }
-
- String escapedText = PATTERN_ESCAPE_SPECIAL_CHARS.matcher(text).replaceAll("////");
- if (!PATTERN_PAGE_RANGE.matcher(escapedText).matches()) {
- mRangeEditText.setError(getString(R.string.invalid_input));
- mPrintButton.setEnabled(false);
- return;
- }
-
- Matcher matcher = PATTERN_DIGITS.matcher(text);
- while (matcher.find()) {
- String numericString = text.substring(matcher.start(), matcher.end());
- final int pageIndex = Integer.parseInt(numericString);
- if (pageIndex < 1 || pageIndex > mPrintDocumentInfo.getPageCount()) {
- mRangeEditText.setError(getString(R.string.invalid_input));
- mPrintButton.setEnabled(false);
- return;
- }
- }
-
- mRangeEditText.setError(null);
- mPrintButton.setEnabled(true);
- }
- };
-
private final DeathRecipient mDeathRecipient = new DeathRecipient() {
@Override
public void binderDied() {
@@ -266,207 +128,21 @@ public class PrintJobConfigActivity extends Activity {
};
@Override
- protected void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- setContentView(R.layout.print_job_config_activity);
-
- getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
- | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
-
- Bundle extras = getIntent().getExtras();
-
- mPrintJobId = extras.getInt(EXTRA_PRINT_JOB_ID, -1);
- if (mPrintJobId < 0) {
- throw new IllegalArgumentException("Invalid print job id: " + mPrintJobId);
- }
-
- mAppId = extras.getInt(EXTRA_APP_ID, -1);
- if (mAppId < 0) {
- throw new IllegalArgumentException("Invalid app id: " + mAppId);
- }
-
- mPrintAttributes = getIntent().getParcelableExtra(EXTRA_ATTRIBUTES);
- if (mPrintAttributes == null) {
- mPrintAttributes = new PrintAttributes.Builder().create();
- }
-
- mIPrintDocumentAdapter = extras.getBinder(EXTRA_PRINTABLE);
- if (mIPrintDocumentAdapter == null) {
- throw new IllegalArgumentException("Printable cannot be null");
- }
- mRemotePrintAdapter = new RemotePrintDocumentAdapter(
- IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
- mPrintSpooler.generateFileForPrintJob(mPrintJobId));
-
- try {
- mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
- } catch (RemoteException re) {
- finish();
- }
-
- mPrinterDiscoveryObserver = new PrintDiscoveryObserver(getMainLooper());
-
- bindUi();
- }
-
- @Override
protected void onDestroy() {
mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
super.onDestroy();
}
- private void bindUi() {
- // Copies
- mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
- mCopiesEditText.setText(String.valueOf(MIN_COPIES));
- mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
-
- // Destination.
- mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
- mDestinationSpinnerAdapter = new ArrayAdapter<SpinnerItem<PrinterInfo>>(this,
- R.layout.spinner_dropdown_item) {
- @Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return getView(position, convertView, parent);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = getLayoutInflater().inflate(
- R.layout.spinner_dropdown_item, parent, false);
- }
-
- PrinterInfo printerInfo = getItem(position).value;
- TextView title = (TextView) convertView.findViewById(R.id.title);
- title.setText(printerInfo.getLabel());
-
- try {
- TextView subtitle = (TextView) convertView.findViewById(R.id.subtitle);
- PackageManager pm = getPackageManager();
- PackageInfo packageInfo = pm.getPackageInfo(
- printerInfo.getId().getService().getPackageName(), 0);
- subtitle.setText(packageInfo.applicationInfo.loadLabel(pm));
- subtitle.setVisibility(View.VISIBLE);
- } catch (NameNotFoundException nnfe) {
- /* ignore */
- }
-
- return convertView;
- }
- };
- mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
- mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
- // Media size.
- mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
- mMediaSizeSpinnerAdapter = new ArrayAdapter<SpinnerItem<MediaSize>>(this,
- R.layout.spinner_dropdown_item, R.id.title);
- mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
- mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
- // Color mode.
- mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
- mColorModeSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
- R.layout.spinner_dropdown_item, R.id.title);
- mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
- mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
- // Orientation
- mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
- mOrientationSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
- R.layout.spinner_dropdown_item, R.id.title);
- mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
- mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
- // Range
- mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
- mRangeEditText.addTextChangedListener(mRangeTextWatcher);
-
- // Range options
- mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
- mRangeOptionsSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
- R.layout.spinner_dropdown_item, R.id.title);
- mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
- mRangeOptionsSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
- final int[] rangeOptionsValues = getResources().getIntArray(
- R.array.page_options_values);
- String[] rangeOptionsLabels = getResources().getStringArray(
- R.array.page_options_labels);
- final int rangeOptionsCount = rangeOptionsLabels.length;
- for (int i = 0; i < rangeOptionsCount; i++) {
- mRangeOptionsSpinnerAdapter.add(new SpinnerItem<Integer>(
- rangeOptionsValues[i], rangeOptionsLabels[i]));
- }
- mRangeOptionsSpinner.setSelection(0);
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ setContentView(R.layout.print_job_config_activity);
- mPrintButton = (Button) findViewById(R.id.print_button);
- mPrintButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mPrintConfirmed = true;
- finish();
- }
- });
- }
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
+ | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
- private void updateUi() {
- final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
- PrinterInfo printer = mDestinationSpinnerAdapter.getItem(selectedIndex).value;
- printer.getDefaults(mPrintAttributes);
-
- // Copies.
- mCopiesEditText.setText(String.valueOf(
- Math.max(mPrintAttributes.getCopies(), MIN_COPIES)));
- mCopiesEditText.selectAll();
-
- // Media size.
- mMediaSizeSpinnerAdapter.clear();
- List<MediaSize> mediaSizes = printer.getMediaSizes();
- final int mediaSizeCount = mediaSizes.size();
- for (int i = 0; i < mediaSizeCount; i++) {
- MediaSize mediaSize = mediaSizes.get(i);
- mMediaSizeSpinnerAdapter.add(new SpinnerItem<MediaSize>(
- mediaSize, mediaSize.getLabel()));
- }
- final int selectedMediaSizeIndex = mediaSizes.indexOf(
- mPrintAttributes.getMediaSize());
- mMediaSizeSpinner.setOnItemSelectedListener(null);
- mMediaSizeSpinner.setSelection(selectedMediaSizeIndex);
-
- // Color mode.
- final int colorModes = printer.getColorModes();
- mColorModeSpinnerAdapter.clear();
- String[] colorModeLabels = getResources().getStringArray(
- R.array.color_mode_labels);
- int remainingColorModes = colorModes;
- while (remainingColorModes != 0) {
- final int colorBitOffset = Integer.numberOfTrailingZeros(remainingColorModes);
- final int colorMode = 1 << colorBitOffset;
- remainingColorModes &= ~colorMode;
- mColorModeSpinnerAdapter.add(new SpinnerItem<Integer>(colorMode,
- colorModeLabels[colorBitOffset]));
- }
- final int selectedColorModeIndex = Integer.numberOfTrailingZeros(
- (colorModes & mPrintAttributes.getColorMode()));
- mColorModeSpinner.setSelection(selectedColorModeIndex);
-
- // Orientation.
- final int orientations = printer.getOrientations();
- mOrientationSpinnerAdapter.clear();
- String[] orientationLabels = getResources().getStringArray(
- R.array.orientation_labels);
- int remainingOrientations = orientations;
- while (remainingOrientations != 0) {
- final int orientationBitOffset = Integer.numberOfTrailingZeros(remainingOrientations);
- final int orientation = 1 << orientationBitOffset;
- remainingOrientations &= ~orientation;
- mOrientationSpinnerAdapter.add(new SpinnerItem<Integer>(orientation,
- orientationLabels[orientationBitOffset]));
- }
- final int selectedOrientationIndex = Integer.numberOfTrailingZeros(
- (orientations & mPrintAttributes.getOrientation()));
- mOrientationSpinner.setSelection(selectedOrientationIndex);
+ mHandler = new MyHandler(Looper.getMainLooper());
+ mEditor = new Editor();
}
@Override
@@ -484,13 +160,12 @@ public class PrintJobConfigActivity extends Activity {
}
private void notifyPrintableStartIfNeeded() {
- if (mDestinationSpinner.getSelectedItemPosition() < 0
+ if (mEditor.getCurrentPrinter() == null
|| mStarted) {
return;
}
mStarted = true;
mRemotePrintAdapter.start();
- updatePrintableContentIfNeeded();
}
private void updatePrintableContentIfNeeded() {
@@ -498,43 +173,66 @@ public class PrintJobConfigActivity extends Activity {
return;
}
- // TODO: Implement old attributes tracking
- mPrintSpooler.setPrintJobAttributes(mPrintJobId, mPrintAttributes);
+ mPrintSpooler.setPrintJobAttributes(mPrintJobId, mCurrPrintAttributes);
+
+ mRemotePrintAdapter.cancel();
+ mHandler.removeMessages(MyHandler.MSG_ON_LAYOUT_FINISHED);
+ mHandler.removeMessages(MyHandler.MSG_ON_LAYOUT_FAILED);
// TODO: Implement setting the print preview attribute
- mRemotePrintAdapter.layout(new PrintAttributes.Builder().create(),
- mPrintAttributes, new LayoutResultCallback() {
+ mRemotePrintAdapter.layout(mOldPrintAttributes,
+ mCurrPrintAttributes, new LayoutResultCallback() {
@Override
public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
- mPrintDocumentInfo = info;
+ mHandler.obtainMessage(MyHandler.MSG_ON_LAYOUT_FINISHED, changed ? 1 : 0,
+ 0, info).sendToTarget();
+ }
- // TODO: Handle the case of unchanged content
- mPrintSpooler.setPrintJobPrintDocumentInfo(mPrintJobId, info);
+ @Override
+ public void onLayoutFailed(CharSequence error) {
+ mHandler.obtainMessage(MyHandler.MSG_ON_LAYOUT_FAILED, error).sendToTarget();
+ }
+ }, new Bundle());
+ }
- // TODO: Implement page selector.
- final List<PageRange> pages = new ArrayList<PageRange>();
- pages.add(PageRange.ALL_PAGES);
+ private void handleOnLayoutFinished(PrintDocumentInfo info, boolean changed) {
+ mPrintDocumentInfo = info;
- mRemotePrintAdapter.write(pages, new WriteResultCallback() {
- @Override
- public void onWriteFinished(List<PageRange> pages) {
- updatePrintPreview(mRemotePrintAdapter.getFile());
- }
+ mEditor.updateUiIfNeeded();
- @Override
- public void onWriteFailed(CharSequence error) {
- Log.e(LOG_TAG, "Error write layout: " + error);
- finishActivity(Activity.RESULT_CANCELED);
- }
- });
+ // TODO: Handle the case of unchanged content
+ mPrintSpooler.setPrintJobPrintDocumentInfo(mPrintJobId, info);
+
+ // TODO: Implement page selector.
+ final List<PageRange> pages = new ArrayList<PageRange>();
+ pages.add(PageRange.ALL_PAGES);
+
+ mRemotePrintAdapter.write(pages, new WriteResultCallback() {
+ @Override
+ public void onWriteFinished(List<PageRange> pages) {
+ mHandler.obtainMessage(MyHandler.MSG_ON_WRITE_FINISHED, pages).sendToTarget();
}
@Override
- public void onLayoutFailed(CharSequence error) {
- Log.e(LOG_TAG, "Error during layout: " + error);
- finishActivity(Activity.RESULT_CANCELED);
+ public void onWriteFailed(CharSequence error) {
+ mHandler.obtainMessage(MyHandler.MSG_ON_WRITE_FAILED, error).sendToTarget();
}
- }, new Bundle());
+ });
+ }
+
+ private void handleOnLayoutFailed(CharSequence error) {
+ Log.e(LOG_TAG, "Error during layout: " + error);
+ finishActivity(Activity.RESULT_CANCELED);
+ }
+
+ private void handleOnWriteFinished(List<PageRange> pages) {
+ // TODO: Now we have to allow the preview button
+ mEditor.updatePrintPreview(mRemotePrintAdapter.getFile());
+ }
+
+ private void handleOnWriteFailed(CharSequence error) {
+ Log.e(LOG_TAG, "Error write layout: " + error);
+ finishActivity(Activity.RESULT_CANCELED);
}
private void notifyPrintableFinishIfNeeded() {
@@ -542,11 +240,14 @@ public class PrintJobConfigActivity extends Activity {
return;
}
- mRemotePrintAdapter.finish(!mPrintConfirmed);
+ if (!mPrintConfirmed) {
+ mRemotePrintAdapter.cancel();
+ }
+ mRemotePrintAdapter.finish();
+ PrinterInfo printer = mEditor.getCurrentPrinter();
// If canceled or no printer, nothing to do.
- final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
- if (!mPrintConfirmed || selectedIndex < 0) {
+ if (!mPrintConfirmed || printer == null) {
// Update the print job's status.
mPrintSpooler.setPrintJobState(mPrintJobId,
PrintJobInfo.STATE_CANCELED);
@@ -554,10 +255,7 @@ public class PrintJobConfigActivity extends Activity {
}
// Update the print job's printer.
- SpinnerItem<PrinterInfo> printerItem =
- mDestinationSpinnerAdapter.getItem(selectedIndex);
- PrinterId printerId = printerItem.value.getId();
- mPrintSpooler.setPrintJobPrinterId(mPrintJobId, printerId);
+ mPrintSpooler.setPrintJobPrinterId(mPrintJobId, printer.getId());
// Update the print job's status.
mPrintSpooler.setPrintJobState(mPrintJobId,
@@ -574,50 +272,11 @@ public class PrintJobConfigActivity extends Activity {
}
}
- private void updatePrintPreview(File file) {
- // TODO: Implement
- }
-
- private void addPrinters(List<PrinterInfo> addedPrinters) {
- final int addedPrinterCount = addedPrinters.size();
- for (int i = 0; i < addedPrinterCount; i++) {
- PrinterInfo addedPrinter = addedPrinters.get(i);
- boolean duplicate = false;
- final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
- for (int j = 0; j < existingPrinterCount; j++) {
- PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
- if (addedPrinter.getId().equals(existingPrinter.getId())) {
- duplicate = true;
- break;
- }
- }
- if (!duplicate) {
- mDestinationSpinnerAdapter.add(new SpinnerItem<PrinterInfo>(
- addedPrinter, addedPrinter.getLabel()));
- } else {
- Log.w(LOG_TAG, "Skipping a duplicate printer: " + addedPrinter);
- }
- }
- }
-
- private void removePrinters(List<PrinterId> pritnerIds) {
- final int printerIdCount = pritnerIds.size();
- for (int i = 0; i < printerIdCount; i++) {
- PrinterId removedPrinterId = pritnerIds.get(i);
- boolean removed = false;
- final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
- for (int j = 0; j < existingPrinterCount; j++) {
- PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
- if (removedPrinterId.equals(existingPrinter.getId())) {
- mDestinationSpinnerAdapter.remove(mDestinationSpinnerAdapter.getItem(j));
- removed = true;
- break;
- }
- }
- if (!removed) {
- Log.w(LOG_TAG, "Ignoring not added printer with id: " + removedPrinterId);
- }
- }
+ private boolean hasPdfViewer() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setType("application/pdf");
+ return !getPackageManager().queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY).isEmpty();
}
// Caution: Use this only for debugging
@@ -659,16 +318,11 @@ public class PrintJobConfigActivity extends Activity {
switch (message.what) {
case MESSAGE_ADD_DICOVERED_PRINTERS: {
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
- addPrinters(printers);
- // Just added the first printer, so select it and start printing.
- if (mDestinationSpinnerAdapter.getCount() == 1) {
- mDestinationSpinner.setSelection(0);
- }
+ mEditor.addPrinters(printers);
} break;
case MESSAGE_REMOVE_DICOVERED_PRINTERS: {
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
- removePrinters(printerIds);
- // TODO: Handle removing the last printer.
+ mEditor.removePrinters(printerIds);
} break;
}
}
@@ -725,6 +379,11 @@ public class PrintJobConfigActivity extends Activity {
return true;
}
+ @Override
+ public void setError(CharSequence error, Drawable icon) {
+ setCompoundDrawables(null, null, icon, null);
+ }
+
protected void onFocusChanged(boolean gainFocus, int direction,
Rect previouslyFocusedRect) {
if (!gainFocus) {
@@ -733,4 +392,611 @@ public class PrintJobConfigActivity extends Activity {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
}
}
+
+ private final class MyHandler extends Handler {
+ public static final int MSG_ON_LAYOUT_FINISHED = 1;
+ public static final int MSG_ON_LAYOUT_FAILED = 2;
+ public static final int MSG_ON_WRITE_FINISHED = 3;
+ public static final int MSG_ON_WRITE_FAILED = 4;
+
+ public MyHandler(Looper looper) {
+ super(looper, null, false);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MSG_ON_LAYOUT_FINISHED: {
+ PrintDocumentInfo info = (PrintDocumentInfo) message.obj;
+ final boolean changed = (message.arg1 == 1);
+ handleOnLayoutFinished(info, changed);
+ } break;
+
+ case MSG_ON_LAYOUT_FAILED: {
+ CharSequence error = (CharSequence) message.obj;
+ handleOnLayoutFailed(error);
+ } break;
+
+ case MSG_ON_WRITE_FINISHED: {
+ List<PageRange> pages = (List<PageRange>) message.obj;
+ handleOnWriteFinished(pages);
+ } break;
+
+ case MSG_ON_WRITE_FAILED: {
+ CharSequence error = (CharSequence) message.obj;
+ handleOnWriteFailed(error);
+ } break;
+ }
+ }
+ }
+
+ private class Editor {
+ private EditText mCopiesEditText;
+
+ private EditText mRangeEditText;
+
+ private Spinner mDestinationSpinner;
+ public ArrayAdapter<SpinnerItem<PrinterInfo>> mDestinationSpinnerAdapter;
+
+ private Spinner mMediaSizeSpinner;
+ public ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
+
+ private Spinner mColorModeSpinner;
+ public ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
+
+ private Spinner mOrientationSpinner;
+ public ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
+
+ private Spinner mRangeOptionsSpinner;
+ public ArrayAdapter<SpinnerItem<Integer>> mRangeOptionsSpinnerAdapter;
+
+ private Button mPrintPreviewButton;
+
+ private Button mPrintButton;
+
+ private final OnItemSelectedListener mOnItemSelectedListener =
+ new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> spinner, View view, int position, long id) {
+ if (spinner == mDestinationSpinner) {
+ mOldPrintAttributes.copyFrom(mCurrPrintAttributes);
+ mCurrPrintAttributes.clear();
+ final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
+ if (selectedIndex >= 0) {
+ mDestinationSpinnerAdapter.getItem(selectedIndex).value.getDefaults(
+ mCurrPrintAttributes);
+ }
+ updateUiIfNeeded();
+ notifyPrintableStartIfNeeded();
+ updatePrintableContentIfNeeded();
+ } else if (spinner == mMediaSizeSpinner) {
+ SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(position);
+ mOldPrintAttributes.copyFrom(mCurrPrintAttributes);
+ mCurrPrintAttributes.setMediaSize(mediaItem.value);
+ updatePrintableContentIfNeeded();
+ } else if (spinner == mColorModeSpinner) {
+ SpinnerItem<Integer> colorModeItem =
+ mColorModeSpinnerAdapter.getItem(position);
+ mOldPrintAttributes.copyFrom(mCurrPrintAttributes);
+ mCurrPrintAttributes.setColorMode(colorModeItem.value);
+ updatePrintableContentIfNeeded();
+ } else if (spinner == mOrientationSpinner) {
+ SpinnerItem<Integer> orientationItem =
+ mOrientationSpinnerAdapter.getItem(position);
+ mOldPrintAttributes.copyFrom(mCurrPrintAttributes);
+ mCurrPrintAttributes.setOrientation(orientationItem.value);
+ updatePrintableContentIfNeeded();
+ } else if (spinner == mRangeOptionsSpinner) {
+ updateUiIfNeeded();
+ updatePrintableContentIfNeeded();
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ /* do nothing*/
+ }
+ };
+
+ private final TextWatcher mCopiesTextWatcher = new TextWatcher() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ /* do nothing */
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ /* do nothing */
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ if (editable.length() == 0) {
+ mCopiesEditText.setError("");
+ mPrintButton.setEnabled(false);
+ return;
+ }
+ final int copies = Integer.parseInt(editable.toString());
+ if (copies < MIN_COPIES) {
+ mCopiesEditText.setError("");
+ mPrintButton.setEnabled(false);
+ return;
+ }
+ mOldPrintAttributes.copyFrom(mCurrPrintAttributes);
+ mCurrPrintAttributes.setCopies(copies);
+ }
+ };
+
+ private final TextWatcher mRangeTextWatcher = new TextWatcher() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ /* do nothing */
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ /* do nothing */
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String text = editable.toString();
+
+ if (TextUtils.isEmpty(text)) {
+ mRangeEditText.setError("");
+ mPrintButton.setEnabled(false);
+ return;
+ }
+
+ String escapedText = PATTERN_ESCAPE_SPECIAL_CHARS.matcher(text).replaceAll("////");
+ if (!PATTERN_PAGE_RANGE.matcher(escapedText).matches()) {
+ mRangeEditText.setError("");
+ mPrintButton.setEnabled(false);
+ return;
+ }
+
+ Matcher matcher = PATTERN_DIGITS.matcher(text);
+ while (matcher.find()) {
+ String numericString = text.substring(matcher.start(), matcher.end());
+ final int pageIndex = Integer.parseInt(numericString);
+ if (pageIndex < 1 || pageIndex > mPrintDocumentInfo.getPageCount()) {
+ mRangeEditText.setError("");
+ mPrintButton.setEnabled(false);
+ return;
+ }
+ }
+
+ mRangeEditText.setError(null);
+ mPrintButton.setEnabled(true);
+ }
+ };
+
+ public Editor() {
+ Bundle extras = getIntent().getExtras();
+
+ mPrintJobId = extras.getInt(EXTRA_PRINT_JOB_ID, -1);
+ if (mPrintJobId < 0) {
+ throw new IllegalArgumentException("Invalid print job id: " + mPrintJobId);
+ }
+
+ mAppId = extras.getInt(EXTRA_APP_ID, -1);
+ if (mAppId < 0) {
+ throw new IllegalArgumentException("Invalid app id: " + mAppId);
+ }
+
+ PrintAttributes attributes = getIntent().getParcelableExtra(EXTRA_ATTRIBUTES);
+ if (attributes == null) {
+ mCurrPrintAttributes.copyFrom(attributes);
+ }
+
+ mIPrintDocumentAdapter = extras.getBinder(EXTRA_PRINTABLE);
+ if (mIPrintDocumentAdapter == null) {
+ throw new IllegalArgumentException("Printable cannot be null");
+ }
+ mRemotePrintAdapter = new RemotePrintDocumentAdapter(
+ IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
+ mPrintSpooler.generateFileForPrintJob(mPrintJobId));
+
+ try {
+ mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException re) {
+ finish();
+ }
+
+ mPrinterDiscoveryObserver = new PrintDiscoveryObserver(getMainLooper());
+
+ bindUi();
+ }
+
+ private void bindUi() {
+ // Copies
+ mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
+ mCopiesEditText.setText(String.valueOf(MIN_COPIES));
+ mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
+ mCopiesEditText.setText(String.valueOf(
+ Math.max(mCurrPrintAttributes.getCopies(), MIN_COPIES)));
+ mCopiesEditText.selectAll();
+
+ // Destination.
+ mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
+ mDestinationSpinnerAdapter = new ArrayAdapter<SpinnerItem<PrinterInfo>>(
+ PrintJobConfigActivity.this, R.layout.spinner_dropdown_item) {
+ @Override
+ public View getDropDownView(int position, View convertView,
+ ViewGroup parent) {
+ return getView(position, convertView, parent);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = getLayoutInflater().inflate(
+ R.layout.spinner_dropdown_item, parent, false);
+ }
+
+ PrinterInfo printerInfo = getItem(position).value;
+ TextView title = (TextView) convertView.findViewById(R.id.title);
+ title.setText(printerInfo.getLabel());
+
+ try {
+ TextView subtitle = (TextView)
+ convertView.findViewById(R.id.subtitle);
+ PackageManager pm = getPackageManager();
+ PackageInfo packageInfo = pm.getPackageInfo(
+ printerInfo.getId().getService().getPackageName(), 0);
+ subtitle.setText(packageInfo.applicationInfo.loadLabel(pm));
+ subtitle.setVisibility(View.VISIBLE);
+ } catch (NameNotFoundException nnfe) {
+ /* ignore */
+ }
+
+ return convertView;
+ }
+ };
+ mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
+ mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+
+ // Media size.
+ mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
+ mMediaSizeSpinnerAdapter = new ArrayAdapter<SpinnerItem<MediaSize>>(
+ PrintJobConfigActivity.this,
+ R.layout.spinner_dropdown_item, R.id.title);
+ mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
+ mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+
+ // Color mode.
+ mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
+ mColorModeSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
+ PrintJobConfigActivity.this,
+ R.layout.spinner_dropdown_item, R.id.title);
+ mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
+ mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+
+ // Orientation
+ mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
+ mOrientationSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
+ PrintJobConfigActivity.this,
+ R.layout.spinner_dropdown_item, R.id.title);
+ mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
+ mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+
+ // Range
+ mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
+ mRangeEditText.addTextChangedListener(mRangeTextWatcher);
+
+ // Range options
+ mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
+ mRangeOptionsSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
+ PrintJobConfigActivity.this,
+ R.layout.spinner_dropdown_item, R.id.title);
+ mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
+ mRangeOptionsSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ final int[] rangeOptionsValues = getResources().getIntArray(
+ R.array.page_options_values);
+ String[] rangeOptionsLabels = getResources().getStringArray(
+ R.array.page_options_labels);
+ final int rangeOptionsCount = rangeOptionsLabels.length;
+ for (int i = 0; i < rangeOptionsCount; i++) {
+ mRangeOptionsSpinnerAdapter.add(new SpinnerItem<Integer>(
+ rangeOptionsValues[i], rangeOptionsLabels[i]));
+ }
+ mRangeOptionsSpinner.setSelection(0);
+
+ mPrintPreviewButton = (Button) findViewById(R.id.print_preview_button);
+ mPrintPreviewButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO: Implement
+ }
+ });
+
+ mPrintButton = (Button) findViewById(R.id.print_button);
+ mPrintButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPrintConfirmed = true;
+ finish();
+ }
+ });
+ }
+
+ private void updateUiIfNeeded() {
+ final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
+
+ if (selectedIndex < 0) {
+ // Destination
+ mDestinationSpinner.setEnabled(false);
+
+ // Copies
+ mCopiesEditText.setText("1");
+ mCopiesEditText.setEnabled(false);
+
+ // Media size
+ mMediaSizeSpinner.setOnItemSelectedListener(null);
+ mMediaSizeSpinner.setSelection(AdapterView.INVALID_POSITION);
+ mMediaSizeSpinner.setEnabled(false);
+
+ // Color mode
+ mColorModeSpinner.setOnItemSelectedListener(null);
+ mColorModeSpinner.setSelection(AdapterView.INVALID_POSITION);
+ mColorModeSpinner.setEnabled(false);
+
+ // Orientation
+ mOrientationSpinner.setOnItemSelectedListener(null);
+ mOrientationSpinner.setSelection(AdapterView.INVALID_POSITION);
+ mOrientationSpinner.setEnabled(false);
+
+ // Range
+ mRangeOptionsSpinner.setOnItemSelectedListener(null);
+ mRangeOptionsSpinner.setSelection(0);
+ mRangeOptionsSpinner.setEnabled(false);
+ mRangeEditText.setText("");
+ mRangeEditText.setEnabled(false);
+ mRangeEditText.setVisibility(View.INVISIBLE);
+
+ // Print preview
+ mPrintPreviewButton.setEnabled(false);
+ mPrintPreviewButton.setText(getString(R.string.print_preview));
+
+ // Print
+ mPrintButton.setEnabled(false);
+ } else {
+ PrintAttributes defaultAttributes = mTempPrintAttributes;
+ PrinterInfo printer = mDestinationSpinnerAdapter.getItem(selectedIndex).value;
+ printer.getDefaults(defaultAttributes);
+
+ // Destination
+ mDestinationSpinner.setEnabled(true);
+
+ // Copies
+ mCopiesEditText.setEnabled(true);
+
+ // Media size.
+ List<MediaSize> mediaSizes = printer.getMediaSizes();
+ boolean mediaSizesChanged = false;
+ final int mediaSizeCount = mediaSizes.size();
+ if (mediaSizeCount != mMediaSizeSpinnerAdapter.getCount()) {
+ mediaSizesChanged = true;
+ } else {
+ for (int i = 0; i < mediaSizeCount; i++) {
+ if (!mediaSizes.get(i).equals(mMediaSizeSpinnerAdapter.getItem(i).value)) {
+ mediaSizesChanged = true;
+ break;
+ }
+ }
+ }
+ if (mediaSizesChanged) {
+ mMediaSizeSpinnerAdapter.clear();
+ for (int i = 0; i < mediaSizeCount; i++) {
+ MediaSize mediaSize = mediaSizes.get(i);
+ mMediaSizeSpinnerAdapter.add(new SpinnerItem<MediaSize>(
+ mediaSize, mediaSize.getLabel()));
+ }
+ if (mediaSizeCount > 0) {
+ mMediaSizeSpinner.setEnabled(true);
+ final int selectedMediaSizeIndex = Math.max(mediaSizes.indexOf(
+ defaultAttributes.getMediaSize()), 0);
+ mMediaSizeSpinner.setOnItemSelectedListener(null);
+ mMediaSizeSpinner.setSelection(selectedMediaSizeIndex);
+ }
+ }
+
+ // Color mode.
+ final int colorModes = printer.getColorModes();
+ boolean colorModesChanged = false;
+ if (Integer.bitCount(colorModes) != mColorModeSpinnerAdapter.getCount()) {
+ colorModesChanged = true;
+ } else {
+ int remainingColorModes = colorModes;
+ while (remainingColorModes != 0) {
+ final int colorBitOffset = Integer.numberOfTrailingZeros(
+ remainingColorModes);
+ final int colorMode = 1 << colorBitOffset;
+ remainingColorModes &= ~colorMode;
+ if (colorMode != mColorModeSpinnerAdapter.getItem(colorBitOffset).value) {
+ colorModesChanged = true;
+ break;
+ }
+ }
+ }
+ if (colorModesChanged) {
+ mColorModeSpinnerAdapter.clear();
+ String[] colorModeLabels = getResources().getStringArray(
+ R.array.color_mode_labels);
+ int remainingColorModes = colorModes;
+ while (remainingColorModes != 0) {
+ final int colorBitOffset = Integer.numberOfTrailingZeros(
+ remainingColorModes);
+ final int colorMode = 1 << colorBitOffset;
+ remainingColorModes &= ~colorMode;
+ mColorModeSpinnerAdapter.add(new SpinnerItem<Integer>(colorMode,
+ colorModeLabels[colorBitOffset]));
+ }
+ if (colorModes > 0) {
+ mColorModeSpinner.setEnabled(true);
+ final int selectedColorModeIndex = Integer.numberOfTrailingZeros(
+ (colorModes & defaultAttributes.getColorMode()));
+ mColorModeSpinner.setOnItemSelectedListener(null);
+ mColorModeSpinner.setSelection(selectedColorModeIndex);
+ }
+ }
+
+ // Orientation.
+ final int orientations = printer.getOrientations();
+ boolean orientationsChanged = false;
+ if (Integer.bitCount(orientations) != mOrientationSpinnerAdapter.getCount()) {
+ orientationsChanged = true;
+ } else {
+ int remainingOrientations = orientations;
+ while (remainingOrientations != 0) {
+ final int orientationBitOffset = Integer.numberOfTrailingZeros(
+ remainingOrientations);
+ final int orientation = 1 << orientationBitOffset;
+ remainingOrientations &= ~orientation;
+ if (orientation != mOrientationSpinnerAdapter.getItem(
+ orientationBitOffset).value) {
+ orientationsChanged = true;
+ break;
+ }
+ }
+ }
+ if (orientationsChanged) {
+ mOrientationSpinnerAdapter.clear();
+ String[] orientationLabels = getResources().getStringArray(
+ R.array.orientation_labels);
+ int remainingOrientations = orientations;
+ while (remainingOrientations != 0) {
+ final int orientationBitOffset = Integer.numberOfTrailingZeros(
+ remainingOrientations);
+ final int orientation = 1 << orientationBitOffset;
+ remainingOrientations &= ~orientation;
+ mOrientationSpinnerAdapter.add(new SpinnerItem<Integer>(orientation,
+ orientationLabels[orientationBitOffset]));
+ }
+ if (orientations > 0) {
+ mOrientationSpinner.setEnabled(true);
+ final int selectedOrientationIndex = Integer.numberOfTrailingZeros(
+ (orientations & defaultAttributes.getOrientation()));
+ mOrientationSpinner.setOnItemSelectedListener(null);
+ mOrientationSpinner.setSelection(selectedOrientationIndex);
+ }
+ }
+
+ // Range options
+ if (mPrintDocumentInfo != null && (mPrintDocumentInfo.getPageCount() > 1
+ || mPrintDocumentInfo.getPageCount()
+ == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)) {
+ mRangeOptionsSpinner.setEnabled(true);
+ if (mRangeOptionsSpinner.getSelectedItemPosition() > 0
+ && !mRangeEditText.isEnabled()) {
+ mRangeEditText.setEnabled(true);
+ mRangeEditText.setError("");
+ mRangeEditText.setVisibility(View.VISIBLE);
+ mRangeEditText.requestFocus();
+ InputMethodManager imm = (InputMethodManager)
+ getSystemService(INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mRangeEditText, 0);
+ }
+ } else {
+ mRangeOptionsSpinner.setOnItemSelectedListener(null);
+ mRangeOptionsSpinner.setSelection(0);
+ mRangeOptionsSpinner.setEnabled(false);
+ mRangeEditText.setEnabled(false);
+ mRangeEditText.setText("");
+ mRangeEditText.setVisibility(View.INVISIBLE);
+ }
+
+ // Print preview
+ mPrintPreviewButton.setEnabled(true);
+ if (hasPdfViewer()) {
+ mPrintPreviewButton.setText(getString(R.string.print_preview));
+ } else {
+ mPrintPreviewButton.setText(getString(R.string.install_for_print_preview));
+ }
+
+ // Print
+ mPrintButton.setEnabled(true);
+ }
+
+ // Here is some voodoo to circumvent the weird behavior of AdapterView
+ // in which a selection listener may get a callback for an event that
+ // happened before the listener was registered. The reason for that is
+ // that the selection change is handled on the next layout pass.
+ Choreographer.getInstance().postCallback(Choreographer.CALLBACK_TRAVERSAL,
+ new Runnable() {
+ @Override
+ public void run() {
+ mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ mRangeOptionsSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ }
+ }, null);
+ }
+
+ public PrinterInfo getCurrentPrinter() {
+ final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
+ if (selectedIndex >= 0) {
+ return mDestinationSpinnerAdapter.getItem(selectedIndex).value;
+ }
+ return null;
+ }
+
+ public void addPrinters(List<PrinterInfo> addedPrinters) {
+ final int addedPrinterCount = addedPrinters.size();
+ for (int i = 0; i < addedPrinterCount; i++) {
+ PrinterInfo addedPrinter = addedPrinters.get(i);
+ boolean duplicate = false;
+ final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
+ for (int j = 0; j < existingPrinterCount; j++) {
+ PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
+ if (addedPrinter.getId().equals(existingPrinter.getId())) {
+ duplicate = true;
+ break;
+ }
+ }
+ if (!duplicate) {
+ mDestinationSpinnerAdapter.add(new SpinnerItem<PrinterInfo>(
+ addedPrinter, addedPrinter.getLabel()));
+ } else {
+ Log.w(LOG_TAG, "Skipping a duplicate printer: " + addedPrinter);
+ }
+ }
+
+ if (mDestinationSpinner.getSelectedItemPosition() == AdapterView.INVALID_POSITION
+ && mDestinationSpinnerAdapter.getCount() > 0) {
+ mDestinationSpinner.setSelection(0);
+ }
+ }
+
+ public void removePrinters(List<PrinterId> pritnerIds) {
+ final int printerIdCount = pritnerIds.size();
+ for (int i = 0; i < printerIdCount; i++) {
+ PrinterId removedPrinterId = pritnerIds.get(i);
+ boolean removed = false;
+ final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
+ for (int j = 0; j < existingPrinterCount; j++) {
+ PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
+ if (removedPrinterId.equals(existingPrinter.getId())) {
+ mDestinationSpinnerAdapter.remove(mDestinationSpinnerAdapter.getItem(j));
+ removed = true;
+ break;
+ }
+ }
+ if (!removed) {
+ Log.w(LOG_TAG, "Ignoring not added printer with id: " + removedPrinterId);
+ }
+ }
+
+ if (mDestinationSpinner.getSelectedItemPosition() != AdapterView.INVALID_POSITION
+ && mDestinationSpinnerAdapter.getCount() == 0) {
+ mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
+ }
+ }
+
+ private void updatePrintPreview(File file) {
+ // TODO: Implement
+ }
+ }
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java
index 2bf62ee..25bb37c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java
@@ -32,6 +32,8 @@ import android.print.PrintDocumentInfo;
import android.util.Log;
import android.util.Slog;
+import libcore.io.IoUtils;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -41,8 +43,6 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
-import libcore.io.IoUtils;
-
/**
* This class represents a remote print document adapter instance.
*/
@@ -53,10 +53,12 @@ final class RemotePrintDocumentAdapter {
public static final int STATE_INITIALIZED = 0;
public static final int STATE_START_COMPLETED = 1;
- public static final int STATE_LAYOUT_COMPLETED = 2;
- public static final int STATE_WRITE_COMPLETED = 3;
- public static final int STATE_FINISH_COMPLETED = 4;
- public static final int STATE_FAILED = 6;
+ public static final int STATE_LAYOUT_STARTED = 2;
+ public static final int STATE_LAYOUT_COMPLETED = 3;
+ public static final int STATE_WRITE_STARTED = 4;
+ public static final int STATE_WRITE_COMPLETED = 5;
+ public static final int STATE_FINISH_COMPLETED = 6;
+ public static final int STATE_FAILED = 7;
private final Object mLock = new Object();
@@ -94,7 +96,6 @@ final class RemotePrintDocumentAdapter {
Log.i(LOG_TAG, "start()");
}
synchronized (mLock) {
- mTaskQueue.add(this);
if (mState != STATE_INITIALIZED) {
throw new IllegalStateException("Invalid state: " + mState);
}
@@ -109,7 +110,15 @@ final class RemotePrintDocumentAdapter {
}
return null;
}
+
+ @Override
+ public void cancel() {
+ /* cannot be cancelled */
+ }
};
+ synchronized (mLock) {
+ mTaskQueue.add(task);
+ }
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
@@ -117,29 +126,37 @@ final class RemotePrintDocumentAdapter {
LayoutResultCallback callback, Bundle metadata) {
LayoutAsyncTask task = new LayoutAsyncTask(oldAttributes, newAttributes, callback,
metadata);
+ synchronized (mLock) {
+ mTaskQueue.add(task);
+ }
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
public void write(List<PageRange> pages, WriteResultCallback callback) {
WriteAsyncTask task = new WriteAsyncTask(pages, callback);
+ synchronized (mLock) {
+ mTaskQueue.add(task);
+ }
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
- public void finish(final boolean abortPendingWork) {
+ public void cancel() {
+ synchronized (mLock) {
+ final int taskCount = mTaskQueue.size();
+ for (int i = taskCount - 1; i >= 0; i--) {
+ mTaskQueue.remove(i).cancel();
+ }
+ }
+ }
+
+ public void finish() {
QueuedAsyncTask task = new QueuedAsyncTask() {
@Override
protected Void doInBackground(Void... params) {
if (DEBUG) {
- Log.i(LOG_TAG, "finish");
+ Log.i(LOG_TAG, "finish()");
}
synchronized (mLock) {
- if (abortPendingWork) {
- final int taskCount = mTaskQueue.size();
- for (int i = taskCount - 1; i >= 0; i--) {
- mTaskQueue.remove(i).cancel();
- }
- }
- mTaskQueue.add(this);
if (mState < STATE_START_COMPLETED) {
return null;
}
@@ -155,7 +172,15 @@ final class RemotePrintDocumentAdapter {
}
return null;
}
+
+ @Override
+ public void cancel() {
+ /* cannot be cancelled */
+ }
};
+ synchronized (mLock) {
+ mTaskQueue.add(task);
+ }
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
@@ -179,6 +204,9 @@ final class RemotePrintDocumentAdapter {
new ILayoutResultCallback.Stub() {
@Override
public void onLayoutStarted(ICancellationSignal cancellationSignal) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onLayoutStarted()");
+ }
synchronized (mLock) {
mCancellationSignal = cancellationSignal;
if (isCancelled()) {
@@ -189,30 +217,43 @@ final class RemotePrintDocumentAdapter {
@Override
public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onLayoutFinished()");
+ }
+ final boolean cancelled;
synchronized (mLock) {
+ cancelled = isCancelled();
mCancellationSignal = null;
- mCompleted = true;
+ mState = STATE_LAYOUT_COMPLETED;
+ mTaskQueue.remove(this);
mLock.notifyAll();
}
- mCallback.onLayoutFinished(info, changed);
+ if (!cancelled) {
+ mCallback.onLayoutFinished(info, changed);
+ }
}
@Override
public void onLayoutFailed(CharSequence error) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onLayoutFailed()");
+ }
+ final boolean cancelled;
synchronized (mLock) {
+ cancelled = isCancelled();
mCancellationSignal = null;
- mCompleted = true;
+ mState = STATE_LAYOUT_COMPLETED;
+ mTaskQueue.remove(this);
mLock.notifyAll();
}
- Slog.e(LOG_TAG, "Error laying out print document: " + error);
- mCallback.onLayoutFailed(error);
+ if (!cancelled) {
+ mCallback.onLayoutFailed(error);
+ }
}
};
private ICancellationSignal mCancellationSignal;
- private boolean mCompleted;
-
public LayoutAsyncTask(PrintAttributes oldAttributes, PrintAttributes newAttributes,
LayoutResultCallback callback, Bundle metadata) {
mOldAttributes = oldAttributes;
@@ -233,25 +274,22 @@ final class RemotePrintDocumentAdapter {
@Override
protected Void doInBackground(Void... params) {
synchronized (mLock) {
- mTaskQueue.add(this);
+ if (DEBUG) {
+ Log.i(LOG_TAG, "layout()");
+ }
if (mState != STATE_START_COMPLETED
&& mState != STATE_LAYOUT_COMPLETED
&& mState != STATE_WRITE_COMPLETED) {
throw new IllegalStateException("Invalid state: " + mState);
}
+ mState = STATE_LAYOUT_STARTED;
}
try {
mRemoteInterface.layout(mOldAttributes, mNewAttributes,
mILayoutResultCallback, mMetadata);
synchronized (mLock) {
while (true) {
- if (isCancelled()) {
- mTaskQueue.remove(this);
- break;
- }
- if (mCompleted) {
- mState = STATE_LAYOUT_COMPLETED;
- mTaskQueue.remove(this);
+ if (mState == STATE_LAYOUT_COMPLETED) {
break;
}
try {
@@ -264,6 +302,8 @@ final class RemotePrintDocumentAdapter {
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error calling layout", re);
mState = STATE_FAILED;
+ mTaskQueue.remove(this);
+ notifyLayoutFailedQuietly();
}
return null;
}
@@ -274,10 +314,19 @@ final class RemotePrintDocumentAdapter {
mCancellationSignal.cancel();
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error cancelling layout", re);
+ notifyLayoutFailedQuietly();
}
}
}
+ public void notifyLayoutFailedQuietly() {
+ try {
+ mILayoutResultCallback.onLayoutFailed(null);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+
private void throwIfCancelledLocked() {
if (isCancelled()) {
throw new IllegalStateException("Already cancelled");
@@ -295,6 +344,9 @@ final class RemotePrintDocumentAdapter {
new IWriteResultCallback.Stub() {
@Override
public void onWriteStarted(ICancellationSignal cancellationSignal) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onWriteStarted()");
+ }
synchronized (mLock) {
mCancellationSignal = cancellationSignal;
if (isCancelled()) {
@@ -305,9 +357,13 @@ final class RemotePrintDocumentAdapter {
@Override
public void onWriteFinished(List<PageRange> pages) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onWriteFinished()");
+ }
synchronized (mLock) {
mCancellationSignal = null;
- mCompleted = true;
+ mState = STATE_WRITE_COMPLETED;
+ mTaskQueue.remove(this);
mLock.notifyAll();
}
mCallback.onWriteFinished(pages);
@@ -315,9 +371,13 @@ final class RemotePrintDocumentAdapter {
@Override
public void onWriteFailed(CharSequence error) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onWriteFailed()");
+ }
synchronized (mLock) {
mCancellationSignal = null;
- mCompleted = true;
+ mState = STATE_WRITE_COMPLETED;
+ mTaskQueue.remove(this);
mLock.notifyAll();
}
Slog.e(LOG_TAG, "Error writing print document: " + error);
@@ -327,8 +387,6 @@ final class RemotePrintDocumentAdapter {
private ICancellationSignal mCancellationSignal;
- private boolean mCompleted;
-
private Thread mWriteThread;
public WriteAsyncTask(List<PageRange> pages, WriteResultCallback callback) {
@@ -349,14 +407,14 @@ final class RemotePrintDocumentAdapter {
@Override
protected Void doInBackground(Void... params) {
if (DEBUG) {
- Log.i(LOG_TAG, "print()");
+ Log.i(LOG_TAG, "write()");
}
synchronized (mLock) {
- mTaskQueue.add(this);
if (mState != STATE_LAYOUT_COMPLETED
&& mState != STATE_WRITE_COMPLETED) {
throw new IllegalStateException("Invalid state: " + mState);
}
+ mState = STATE_WRITE_STARTED;
}
InputStream in = null;
OutputStream out = null;
@@ -394,13 +452,7 @@ final class RemotePrintDocumentAdapter {
}
synchronized (mLock) {
while (true) {
- if (isCancelled()) {
- mTaskQueue.remove(this);
- break;
- }
- if (mCompleted) {
- mState = STATE_WRITE_COMPLETED;
- mTaskQueue.remove(this);
+ if (mState == STATE_WRITE_COMPLETED) {
break;
}
try {
@@ -413,9 +465,13 @@ final class RemotePrintDocumentAdapter {
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error writing print document", re);
mState = STATE_FAILED;
+ mTaskQueue.remove(this);
+ notifyWriteFailedQuietly();
} catch (IOException ioe) {
Slog.e(LOG_TAG, "Error writing print document", ioe);
mState = STATE_FAILED;
+ mTaskQueue.remove(this);
+ notifyWriteFailedQuietly();
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
@@ -431,10 +487,19 @@ final class RemotePrintDocumentAdapter {
mCancellationSignal.cancel();
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error cancelling layout", re);
+ notifyWriteFailedQuietly();
}
}
}
+ private void notifyWriteFailedQuietly() {
+ try {
+ mIWriteResultCallback.onWriteFailed(null);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+
private void throwIfCancelledLocked() {
if (isCancelled()) {
throw new IllegalStateException("Already cancelled");