Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 948c9a63 authored by Svetoslav's avatar Svetoslav Committed by Svetoslav Ganov
Browse files

Add duplex mode support.

This change adds support for duplex printing. The print UI now has a duplex
option which allows the user to choose one of the supported duplex options
by the currently selected printer. The chosen duplex mode is propaged to the
print service that manages this printer.

Change-Id: I807ba9da2723531535c0e1e33f2f4e1b503a54b0
parent d7596cff
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -23234,6 +23234,7 @@ package android.print {
  public final class PrintAttributes implements android.os.Parcelable {
    method public int describeContents();
    method public int getColorMode();
    method public int getDuplexMode();
    method public android.print.PrintAttributes.MediaSize getMediaSize();
    method public android.print.PrintAttributes.Margins getMinMargins();
    method public android.print.PrintAttributes.Resolution getResolution();
@@ -23241,12 +23242,16 @@ package android.print {
    field public static final int COLOR_MODE_COLOR = 2; // 0x2
    field public static final int COLOR_MODE_MONOCHROME = 1; // 0x1
    field public static final android.os.Parcelable.Creator<android.print.PrintAttributes> CREATOR;
    field public static final int DUPLEX_MODE_LONG_EDGE = 2; // 0x2
    field public static final int DUPLEX_MODE_NONE = 1; // 0x1
    field public static final int DUPLEX_MODE_SHORT_EDGE = 4; // 0x4
  }
  public static final class PrintAttributes.Builder {
    ctor public PrintAttributes.Builder();
    method public android.print.PrintAttributes build();
    method public android.print.PrintAttributes.Builder setColorMode(int);
    method public android.print.PrintAttributes.Builder setDuplexMode(int);
    method public android.print.PrintAttributes.Builder setMediaSize(android.print.PrintAttributes.MediaSize);
    method public android.print.PrintAttributes.Builder setMinMargins(android.print.PrintAttributes.Margins);
    method public android.print.PrintAttributes.Builder setResolution(android.print.PrintAttributes.Resolution);
@@ -23464,6 +23469,7 @@ package android.print {
    method public int describeContents();
    method public int getColorModes();
    method public android.print.PrintAttributes getDefaults();
    method public int getDuplexModes();
    method public java.util.List<android.print.PrintAttributes.MediaSize> getMediaSizes();
    method public android.print.PrintAttributes.Margins getMinMargins();
    method public java.util.List<android.print.PrintAttributes.Resolution> getResolutions();
@@ -23477,6 +23483,7 @@ package android.print {
    method public android.print.PrinterCapabilitiesInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
    method public android.print.PrinterCapabilitiesInfo build();
    method public android.print.PrinterCapabilitiesInfo.Builder setColorModes(int, int);
    method public android.print.PrinterCapabilitiesInfo.Builder setDuplexModes(int, int);
    method public android.print.PrinterCapabilitiesInfo.Builder setMinMargins(android.print.PrintAttributes.Margins);
  }
+7 −0
Original line number Diff line number Diff line
@@ -24823,6 +24823,7 @@ package android.print {
  public final class PrintAttributes implements android.os.Parcelable {
    method public int describeContents();
    method public int getColorMode();
    method public int getDuplexMode();
    method public android.print.PrintAttributes.MediaSize getMediaSize();
    method public android.print.PrintAttributes.Margins getMinMargins();
    method public android.print.PrintAttributes.Resolution getResolution();
@@ -24830,12 +24831,16 @@ package android.print {
    field public static final int COLOR_MODE_COLOR = 2; // 0x2
    field public static final int COLOR_MODE_MONOCHROME = 1; // 0x1
    field public static final android.os.Parcelable.Creator<android.print.PrintAttributes> CREATOR;
    field public static final int DUPLEX_MODE_LONG_EDGE = 2; // 0x2
    field public static final int DUPLEX_MODE_NONE = 1; // 0x1
    field public static final int DUPLEX_MODE_SHORT_EDGE = 4; // 0x4
  }
  public static final class PrintAttributes.Builder {
    ctor public PrintAttributes.Builder();
    method public android.print.PrintAttributes build();
    method public android.print.PrintAttributes.Builder setColorMode(int);
    method public android.print.PrintAttributes.Builder setDuplexMode(int);
    method public android.print.PrintAttributes.Builder setMediaSize(android.print.PrintAttributes.MediaSize);
    method public android.print.PrintAttributes.Builder setMinMargins(android.print.PrintAttributes.Margins);
    method public android.print.PrintAttributes.Builder setResolution(android.print.PrintAttributes.Resolution);
@@ -25053,6 +25058,7 @@ package android.print {
    method public int describeContents();
    method public int getColorModes();
    method public android.print.PrintAttributes getDefaults();
    method public int getDuplexModes();
    method public java.util.List<android.print.PrintAttributes.MediaSize> getMediaSizes();
    method public android.print.PrintAttributes.Margins getMinMargins();
    method public java.util.List<android.print.PrintAttributes.Resolution> getResolutions();
@@ -25066,6 +25072,7 @@ package android.print {
    method public android.print.PrinterCapabilitiesInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
    method public android.print.PrinterCapabilitiesInfo build();
    method public android.print.PrinterCapabilitiesInfo.Builder setColorModes(int, int);
    method public android.print.PrinterCapabilitiesInfo.Builder setDuplexModes(int, int);
    method public android.print.PrinterCapabilitiesInfo.Builder setMinMargins(android.print.PrintAttributes.Margins);
  }
+100 −9
Original line number Diff line number Diff line
@@ -45,11 +45,22 @@ public final class PrintAttributes implements Parcelable {
    private static final int VALID_COLOR_MODES =
            COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR;

    /** Duplex mode: No duplexing. */
    public static final int DUPLEX_MODE_NONE = 1 << 0;
    /** Duplex mode: Pages are turned sideways along the long edge - like a book. */
    public static final int DUPLEX_MODE_LONG_EDGE = 1 << 1;
    /** Duplex mode: Pages are turned upwards along the short edge - like a notpad. */
    public static final int DUPLEX_MODE_SHORT_EDGE = 1 << 2;

    private static final int VALID_DUPLEX_MODES =
            DUPLEX_MODE_NONE | DUPLEX_MODE_LONG_EDGE | DUPLEX_MODE_SHORT_EDGE;

    private MediaSize mMediaSize;
    private Resolution mResolution;
    private Margins mMinMargins;

    private int mColorMode;
    private int mDuplexMode = DUPLEX_MODE_NONE;

    PrintAttributes() {
        /* hide constructor */
@@ -60,6 +71,7 @@ public final class PrintAttributes implements Parcelable {
        mResolution = (parcel.readInt() ==  1) ? Resolution.createFromParcel(parcel) : null;
        mMinMargins = (parcel.readInt() ==  1) ? Margins.createFromParcel(parcel) : null;
        mColorMode = parcel.readInt();
        mDuplexMode = parcel.readInt();
    }

    /**
@@ -74,7 +86,7 @@ public final class PrintAttributes implements Parcelable {
    /**
     * Sets the media size.
     *
     * @param The media size.
     * @param mediaSize The media size.
     *
     * @hide
     */
@@ -94,7 +106,7 @@ public final class PrintAttributes implements Parcelable {
    /**
     * Sets the resolution.
     *
     * @param The resolution.
     * @param resolution The resolution.
     *
     * @hide
     */
@@ -130,7 +142,7 @@ public final class PrintAttributes implements Parcelable {
     * </strong>
     * </p>
     *
     * @param The margins.
     * @param margins The margins.
     *
     * @hide
     */
@@ -153,7 +165,7 @@ public final class PrintAttributes implements Parcelable {
    /**
     * Sets the color mode.
     *
     * @param The color mode.
     * @param colorMode The color mode.
     *
     * @see #COLOR_MODE_MONOCHROME
     * @see #COLOR_MODE_COLOR
@@ -178,6 +190,35 @@ public final class PrintAttributes implements Parcelable {
        return mMediaSize.isPortrait();
    }

    /**
     * Gets the duplex mode.
     *
     * @return The duplex mode.
     *
     * @see #DUPLEX_MODE_NONE
     * @see #DUPLEX_MODE_LONG_EDGE
     * @see #DUPLEX_MODE_SHORT_EDGE
     */
    public int getDuplexMode() {
        return mDuplexMode;
    }

    /**
     * Sets the duplex mode.
     *
     * @param duplexMode The duplex mode.
     *
     * @see #DUPLEX_MODE_NONE
     * @see #DUPLEX_MODE_LONG_EDGE
     * @see #DUPLEX_MODE_SHORT_EDGE
     *
     * @hide
     */
    public void setDuplexMode(int duplexMode) {
        enforceValidDuplexMode(duplexMode);
        mDuplexMode = duplexMode;
    }

    /**
     * Gets a new print attributes instance which is in portrait orientation,
     * which is the media size is in portrait and all orientation dependent
@@ -211,6 +252,7 @@ public final class PrintAttributes implements Parcelable {
        attributes.setMinMargins(getMinMargins());

        attributes.setColorMode(getColorMode());
        attributes.setDuplexMode(getDuplexMode());

        return attributes;
    }
@@ -248,6 +290,7 @@ public final class PrintAttributes implements Parcelable {
        attributes.setMinMargins(getMinMargins());

        attributes.setColorMode(getColorMode());
        attributes.setDuplexMode(getDuplexMode());

        return attributes;
    }
@@ -273,6 +316,7 @@ public final class PrintAttributes implements Parcelable {
            parcel.writeInt(0);
        }
        parcel.writeInt(mColorMode);
        parcel.writeInt(mDuplexMode);
    }

    @Override
@@ -285,6 +329,7 @@ public final class PrintAttributes implements Parcelable {
        final int prime = 31;
        int result = 1;
        result = prime * result + mColorMode;
        result = prime * result + mDuplexMode;
        result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
        result = prime * result + ((mMediaSize == null) ? 0 : mMediaSize.hashCode());
        result = prime * result + ((mResolution == null) ? 0 : mResolution.hashCode());
@@ -306,6 +351,9 @@ public final class PrintAttributes implements Parcelable {
        if (mColorMode != other.mColorMode) {
            return false;
        }
        if (mDuplexMode != other.mDuplexMode) {
            return false;
        }
        if (mMinMargins == null) {
            if (other.mMinMargins != null) {
                return false;
@@ -344,6 +392,7 @@ public final class PrintAttributes implements Parcelable {
        builder.append(", resolution: ").append(mResolution);
        builder.append(", minMargins: ").append(mMinMargins);
        builder.append(", colorMode: ").append(colorModeToString(mColorMode));
        builder.append(", duplexMode: ").append(duplexModeToString(mDuplexMode));
        builder.append("}");
        return builder.toString();
    }
@@ -354,6 +403,7 @@ public final class PrintAttributes implements Parcelable {
        mResolution = null;
        mMinMargins = null;
        mColorMode = 0;
        mDuplexMode = DUPLEX_MODE_NONE;
    }

    /**
@@ -364,6 +414,7 @@ public final class PrintAttributes implements Parcelable {
        mResolution = other.mResolution;
        mMinMargins = other.mMinMargins;
        mColorMode = other.mColorMode;
        mDuplexMode = other.mDuplexMode;
    }

    /**
@@ -1270,17 +1321,41 @@ public final class PrintAttributes implements Parcelable {
            case COLOR_MODE_COLOR: {
                return "COLOR_MODE_COLOR";
            }
            default:
            default: {
                return "COLOR_MODE_UNKNOWN";
            }
        }
    }

    static String duplexModeToString(int duplexMode) {
        switch (duplexMode) {
            case DUPLEX_MODE_NONE: {
                return "DUPLEX_MODE_NONE";
            }
            case DUPLEX_MODE_LONG_EDGE: {
                return "DUPLEX_MODE_LONG_EDGE";
            }
            case DUPLEX_MODE_SHORT_EDGE: {
                return "DUPLEX_MODE_SHORT_EDGE";
            }
            default: {
                return "DUPLEX_MODE_UNKNOWN";
            }
        }
    }

    static void enforceValidColorMode(int colorMode) {
        if ((colorMode & VALID_COLOR_MODES) == 0 && Integer.bitCount(colorMode) == 1) {
        if ((colorMode & VALID_COLOR_MODES) == 0 || Integer.bitCount(colorMode) != 1) {
            throw new IllegalArgumentException("invalid color mode: " + colorMode);
        }
    }

    static void enforceValidDuplexMode(int duplexMode) {
        if ((duplexMode & VALID_DUPLEX_MODES) == 0 || Integer.bitCount(duplexMode) != 1) {
            throw new IllegalArgumentException("invalid duplex mode: " + duplexMode);
        }
    }

    /**
     * Builder for creating {@link PrintAttributes}.
     */
@@ -1331,15 +1406,31 @@ public final class PrintAttributes implements Parcelable {
         * @see PrintAttributes#COLOR_MODE_COLOR
         */
        public Builder setColorMode(int colorMode) {
            if (Integer.bitCount(colorMode) > 1) {
                throw new IllegalArgumentException("can specify at most one colorMode bit.");
            }
            mAttributes.setColorMode(colorMode);
            return this;
        }

        /**
         * Sets the duplex mode.
         *
         * @param duplexMode A valid duplex mode or zero.
         * @return This builder.
         *
         * @see PrintAttributes#DUPLEX_MODE_NONE
         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
         */
        public Builder setDuplexMode(int duplexMode) {
            mAttributes.setDuplexMode(duplexMode);
            return this;
        }

        /**
         * Creates a new {@link PrintAttributes} instance.
         * <p>
         * If you do not specify a duplex mode, the default
         * {@link #DUPLEX_MODE_NONE} will be used.
         * </p>
         *
         * @return The new instance.
         */
+85 −6
Original line number Diff line number Diff line
@@ -47,7 +47,8 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
    private static final int PROPERTY_MEDIA_SIZE = 0;
    private static final int PROPERTY_RESOLUTION = 1;
    private static final int PROPERTY_COLOR_MODE = 2;
    private static final int PROPERTY_COUNT = 3;
    private static final int PROPERTY_DUPLEX_MODE = 3;
    private static final int PROPERTY_COUNT = 4;

    private static final Margins DEFAULT_MARGINS = new Margins(0,  0,  0,  0);

@@ -56,6 +57,7 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
    private List<Resolution> mResolutions;

    private int mColorModes;
    private int mDuplexModes;

    private final int[] mDefaults = new int[PROPERTY_COUNT];

@@ -106,6 +108,7 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        }

        mColorModes = other.mColorModes;
        mDuplexModes = other.mDuplexModes;

        final int defaultCount = other.mDefaults.length;
        for (int i = 0; i < defaultCount; i++) {
@@ -153,6 +156,19 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        return mColorModes;
    }

    /**
     * Gets the bit mask of supported duplex modes.
     *
     * @return The bit mask of supported duplex modes.
     *
     * @see PrintAttributes#DUPLEX_MODE_NONE
     * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
     * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
     */
    public int getDuplexModes() {
        return mDuplexModes;
    }

    /**
     * Gets the default print attributes.
     *
@@ -178,6 +194,11 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
            builder.setColorMode(colorMode);
        }

        final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
        if (duplexMode > 0) {
            builder.setDuplexMode(duplexMode);
        }

        return builder.build();
    }

@@ -187,6 +208,7 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        readResolutions(parcel);

        mColorModes = parcel.readInt();
        mDuplexModes = parcel.readInt();

        readDefaults(parcel);
    }
@@ -203,6 +225,7 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        writeResolutions(parcel);

        parcel.writeInt(mColorModes);
        parcel.writeInt(mDuplexModes);

        writeDefaults(parcel);
    }
@@ -215,6 +238,7 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
        result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
        result = prime * result + mColorModes;
        result = prime * result + mDuplexModes;
        result = prime * result + Arrays.hashCode(mDefaults);
        return result;
    }
@@ -255,6 +279,9 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        if (mColorModes != other.mColorModes) {
            return false;
        }
        if (mDuplexModes != other.mDuplexModes) {
            return false;
        }
        if (!Arrays.equals(mDefaults, other.mDefaults)) {
            return false;
        }
@@ -269,6 +296,7 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        builder.append(", mediaSizes=").append(mMediaSizes);
        builder.append(", resolutions=").append(mResolutions);
        builder.append(", colorModes=").append(colorModesToString());
        builder.append(", duplexModes=").append(duplexModesToString());
        builder.append("\"}");
        return builder.toString();
    }
@@ -289,6 +317,22 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        return builder.toString();
    }

    private String duplexModesToString() {
        StringBuilder builder = new StringBuilder();
        builder.append('[');
        int duplexModes = mDuplexModes;
        while (duplexModes != 0) {
            final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
            duplexModes &= ~duplexMode;
            if (builder.length() > 1) {
                builder.append(", ");
            }
            builder.append(PrintAttributes.duplexModeToString(duplexMode));
        }
        builder.append(']');
        return builder.toString();
    }

    private void writeMediaSizes(Parcel parcel) {
        if (mMediaSizes == null) {
            parcel.writeInt(0);
@@ -495,19 +539,51 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
                currentModes &= ~currentMode;
                PrintAttributes.enforceValidColorMode(currentMode);
            }
            if ((colorModes & defaultColorMode) == 0) {
                throw new IllegalArgumentException("Default color mode not in color modes.");
            }
            PrintAttributes.enforceValidColorMode(colorModes);
            PrintAttributes.enforceValidColorMode(defaultColorMode);
            mPrototype.mColorModes = colorModes;
            mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
            return this;
        }

        /**
         * Sets the duplex modes.
         * <p>
         * <strong>Required:</strong> No
         * </p>
         *
         * @param duplexModes The duplex mode bit mask.
         * @param defaultDuplexMode The default duplex mode.
         * @return This builder.
         *
         * @throws IllegalArgumentException If duplex modes contains an invalid
         *         mode bit or if the default duplex mode is invalid.
         *
         * @see PrintAttributes#DUPLEX_MODE_NONE
         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
         */
        public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
            int currentModes = duplexModes;
            while (currentModes > 0) {
                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
                currentModes &= ~currentMode;
                PrintAttributes.enforceValidDuplexMode(currentMode);
            }
            PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
            mPrototype.mDuplexModes = duplexModes;
            mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
            return this;
        }

        /**
         * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
         * required properties have been specified. See individual methods
         * in this class for reference about required attributes.
         * <p>
         * <strong>Note:</strong> If you do not add supported duplex modes,
         * {@link android.print.PrintAttributes#DUPLEX_MODE_NONE} will set
         * as the only supported mode and also as the default duplex mode.
         * </p>
         *
         * @return A new {@link PrinterCapabilitiesInfo}.
         *
@@ -532,6 +608,10 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
            if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
                throw new IllegalStateException("No default color mode specified.");
            }
            if (mPrototype.mDuplexModes == 0) {
                setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
                        PrintAttributes.DUPLEX_MODE_NONE);
            }
            if (mPrototype.mMinMargins == null) {
                throw new IllegalArgumentException("margins cannot be null");
            }
@@ -558,4 +638,3 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
        }
    };
}
+28 −0
Original line number Diff line number Diff line
@@ -152,6 +152,34 @@

            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dip"
                android:layout_marginEnd="16dip"
                android:orientation="vertical">

                <!-- Duplex -->

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="8dip"
                    android:layout_marginStart="12dip"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:labelFor="@+id/duplex_spinner"
                    android:text="@string/label_duplex">
                </TextView>

                <Spinner
                    android:id="@+id/duplex_spinner"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="4dip">
                </Spinner>

            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
Loading