[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: ad7d1aef49 -s ours
am skip reason: subject contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/BuiltInPrintService/+/22980528
Change-Id: Ic14a4c40e4aa74763f9502724ade42c05669624f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/OWNERS b/OWNERS
index e2a1aec..dc1919c 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1,2 @@
-svetoslavganov@google.com
+# Bug component: 47273
+include platform/frameworks/base:/OWNERS
diff --git a/jni/include/ifc_print_job.h b/jni/include/ifc_print_job.h
index 0c0fc2a..c64a807 100644
--- a/jni/include/ifc_print_job.h
+++ b/jni/include/ifc_print_job.h
@@ -34,14 +34,14 @@
/*
* Validates job and connection params, updating parameters as necessary.
*/
- status_t (*validate_job)(const struct ifc_print_job_st *this_p,
- wprint_job_params_t *job_params);
+ status_t (*validate_job)(const struct ifc_print_job_st *this_p, wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_caps);
/*
* Start a print job with given params
*/
status_t (*start_job)(const struct ifc_print_job_st *this_p,
- const wprint_job_params_t *job_params);
+ const wprint_job_params_t *job_params, const printer_capabilities_t *printer_caps);
/*
* Sends data to the ip address set on initialization, returning the amount of data
diff --git a/jni/include/lib_wprint.h b/jni/include/lib_wprint.h
index b60e539..6c1d26e 100755
--- a/jni/include/lib_wprint.h
+++ b/jni/include/lib_wprint.h
@@ -134,14 +134,16 @@
color_space_t color_space;
media_tray_t media_tray;
unsigned int num_copies;
+ unsigned int job_pages_per_set;
bool borderless;
unsigned int render_flags;
float job_top_margin;
float job_left_margin;
float job_right_margin;
float job_bottom_margin;
+ bool preserve_scaling;
- bool renderInReverseOrder;
+ bool face_down_tray;
// these values are pixels
unsigned int print_top_margin;
@@ -190,6 +192,7 @@
const char *useragent;
char docCategory[10];
const char *media_default;
+ char print_scaling[MAX_PRINT_SCALING_LENGTH];
// Expected certificate if any
uint8 *certificate;
@@ -221,7 +224,8 @@
/* Timeout per retry in milliseconds */
long timeout;
/* Return non-0 if the received certificate is not acceptable. */
- int (*validate_certificate)(struct wprint_connect_info_st *connect_info, uint8 *data, int data_len);
+ int (*validate_certificate)(struct wprint_connect_info_st *connect_info,
+ uint8 *data, int data_len);
/* User-supplied data. */
void *user;
};
@@ -249,7 +253,6 @@
int current_page;
int total_pages;
int page_total_update;
-
} wprint_page_info_t;
typedef struct {
@@ -290,8 +293,8 @@
status_t (*print_page)(wprint_job_params_t *job_params, const char *mime_type,
const char *pathname);
- status_t (*print_blank_page)(wJob_t job_handle,
- wprint_job_params_t *job_params);
+ status_t (*print_blank_page)(wJob_t job_handle, wprint_job_params_t *job_params,
+ const char *mime_type, const char *pathname);
status_t (*end_job)(wprint_job_params_t *job_params);
} wprint_plugin_t;
@@ -314,6 +317,12 @@
printer_capabilities_t *printer_cap);
/*
+ * Returns a preferred print format supported by the printer
+ */
+char *_get_print_format(const char *mime_type, const wprint_job_params_t *job_params,
+ const printer_capabilities_t *cap);
+
+/*
* Fills in the job params structure with default values.
*/
status_t wprintGetDefaultJobParams(wprint_job_params_t *job_params);
@@ -367,6 +376,18 @@
*/
void wprintSetSourceInfo(const char *appName, const char *appVersion, const char *osName);
+/*
+ * Returns true, if a blank page to be printed in duplex print for PCLm
+ */
+bool wprintBlankPageForPclm(const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_cap);
+
+/*
+ * Returns true, if a blank page to be printed in duplex print for PWG
+ */
+bool wprintBlankPageForPwg(const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_cap);
+
/* Global variables to hold API, application, and OS details */
extern int g_API_version;
extern char g_osName[MAX_ID_STRING_LENGTH + 1];
diff --git a/jni/include/printer_capabilities_types.h b/jni/include/printer_capabilities_types.h
index 90cb581..6313a31 100644
--- a/jni/include/printer_capabilities_types.h
+++ b/jni/include/printer_capabilities_types.h
@@ -26,6 +26,8 @@
#define MAX_URI_LENGTH 1024
#define MAX_STRING 256
#define MAX_UUID 46
+#define MAX_PRINT_SCALING_LENGTH 32
+#define MAX_PRINT_SCALING_COUNT 10
#include "wprint_df_types.h"
@@ -44,6 +46,7 @@
*/
typedef struct {
unsigned char duplex;
+ unsigned char sidesSupported;
unsigned char borderless;
unsigned char canPrintPDF;
unsigned char canPrintPCLm;
@@ -91,6 +94,10 @@
unsigned char docSourceAppVersion;
unsigned char docSourceOsName;
unsigned char docSourceOsVersion;
+ char print_scalings_supported[MAX_PRINT_SCALING_COUNT][MAX_PRINT_SCALING_LENGTH];
+ int print_scalings_supported_count;
+ char print_scaling_default[MAX_PRINT_SCALING_LENGTH]; /* Printer default value */
+ unsigned char jobPagesPerSetSupported;
} printer_capabilities_t;
#endif // __PRINTER_CAPABILITIES_TYPES_H__
\ No newline at end of file
diff --git a/jni/include/wprint_status_types.h b/jni/include/wprint_status_types.h
index 83758b7..b1449bc 100644
--- a/jni/include/wprint_status_types.h
+++ b/jni/include/wprint_status_types.h
@@ -41,7 +41,6 @@
#define BLOCKED_REASON_CANCELLED (1 << PRINT_STATUS_CANCELLED)
#define BLOCKED_REASON_PRINT_STATUS_VERY_LOW_ON_INK (1 << PRINT_STATUS_VERY_LOW_ON_INK)
#define BLOCKED_REASON_PARTIAL_CANCEL (1 << PRINT_STATUS_PARTIAL_CANCEL)
-#define BLOCKED_REASON_BAD_CERTIFICATE (1 << PRINT_STATUS_BAD_CERTIFICATE)
#define BLOCKED_REASON_PAUSED (LONG_ONE << PRINT_STATUS_PAUSED)
#define BLOCKED_REASON_STOPPED (LONG_ONE << PRINT_STATUS_STOPPED)
#define BLOCKED_REASON_INPUT_CANNOT_FEED_SIZE_SELECTED \
@@ -153,7 +152,6 @@
PRINT_STATUS_VERY_LOW_ON_INK,
PRINT_STATUS_PARTIAL_CANCEL,
- PRINT_STATUS_BAD_CERTIFICATE,
PRINT_STATUS_INPUT_CANNOT_FEED_SIZE_SELECTED,
PRINT_STATUS_INTERLOCK_ERROR,
diff --git a/jni/include/wtypes.h b/jni/include/wtypes.h
index 764d6b0..29ed6b0 100644
--- a/jni/include/wtypes.h
+++ b/jni/include/wtypes.h
@@ -36,6 +36,9 @@
/* Request failed because corrupt data was detected */
CORRUPT = -3,
+
+ /* Request failed because unexpected ssl certificate received */
+ BAD_CERTIFICATE = -4
} status_t;
#define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0]))
diff --git a/jni/ipphelper/ipp_print.c b/jni/ipphelper/ipp_print.c
index 785fd9a..a95b2db 100644
--- a/jni/ipphelper/ipp_print.c
+++ b/jni/ipphelper/ipp_print.c
@@ -28,9 +28,11 @@
static status_t _init(const ifc_print_job_t *this_p, const char *printer_address, int port,
const char *printer_uri, bool use_secure_uri);
-static status_t _validate_job(const ifc_print_job_t *this_p, wprint_job_params_t *job_params);
+static status_t _validate_job(const ifc_print_job_t *this_p, wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_caps);
-static status_t _start_job(const ifc_print_job_t *this_p, const wprint_job_params_t *job_params);
+static status_t _start_job(const ifc_print_job_t *this_p, const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_caps);
static int _send_data(const ifc_print_job_t *this_p, const char *buffer, size_t length);
@@ -170,7 +172,8 @@
/*
* Fills and returns an ipp request object with the given job parameters
*/
-static ipp_t *_fill_job(int ipp_op, char *printer_uri, const wprint_job_params_t *job_params) {
+static ipp_t *_fill_job(int ipp_op, char *printer_uri, const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_caps) {
LOGD("_fill_job: Enter");
ipp_t *request = NULL; // IPP request object
ipp_attribute_t *attrptr; // Attribute pointer
@@ -291,11 +294,29 @@
}
}
+ // Add print-scaling attribute to the request
+ if (strlen(job_params->print_scaling) != 0) {
+ LOGD("_fill_job: setting print-scaling to %s", job_params->print_scaling);
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "print-scaling",
+ NULL, job_params->print_scaling);
+ }
+
// Add copies support if required and allowed
if (job_params->copies_supported && (strcmp(job_params->print_format, PRINT_FORMAT_PDF) == 0)) {
ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", job_params->num_copies);
}
+ if (printer_caps->jobPagesPerSetSupported && job_params->job_pages_per_set > 0) {
+ unsigned int job_pages_per_set = job_params->job_pages_per_set;
+ if (strcmp(job_params->print_format, PRINT_FORMAT_PCLM) == 0
+ && wprintBlankPageForPclm(job_params, printer_caps)) {
+ job_pages_per_set++;
+ LOGD("_fill_job: incremented job_pages_per_set: %d", job_pages_per_set);
+ }
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set",
+ job_pages_per_set);
+ }
+
// Add print quality if requested
if (job_params->print_quality) {
ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
@@ -304,15 +325,18 @@
ippAddResolution(request, IPP_TAG_JOB, "printer-resolution", IPP_RES_PER_INCH,
job_params->pixel_units, job_params->pixel_units);
- if (job_params->duplex == DUPLEX_MODE_BOOK) {
- ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, IPP_SIDES_TAG, NULL,
- IPP_SIDES_TWO_SIDED_LONG_EDGE);
- } else if (job_params->duplex == DUPLEX_MODE_TABLET) {
- ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, IPP_SIDES_TAG, NULL,
- IPP_SIDES_TWO_SIDED_SHORT_EDGE);
- } else {
- ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, IPP_SIDES_TAG, NULL,
- IPP_SIDES_ONE_SIDED);
+
+ if (printer_caps->sidesSupported) {
+ if (job_params->duplex == DUPLEX_MODE_BOOK) {
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, IPP_SIDES_TAG, NULL,
+ IPP_SIDES_TWO_SIDED_LONG_EDGE);
+ } else if (job_params->duplex == DUPLEX_MODE_TABLET) {
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, IPP_SIDES_TAG, NULL,
+ IPP_SIDES_TWO_SIDED_SHORT_EDGE);
+ } else {
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, IPP_SIDES_TAG, NULL,
+ IPP_SIDES_ONE_SIDED);
+ }
}
if (job_params->color_space == COLOR_SPACE_MONO) {
@@ -409,7 +433,8 @@
return request;
}
-static status_t _validate_job(const ifc_print_job_t *this_p, wprint_job_params_t *job_params) {
+static status_t _validate_job(const ifc_print_job_t *this_p, wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_caps) {
LOGD("_validate_job: Enter");
status_t result = ERROR;
ipp_print_job_t *ipp_job;
@@ -437,7 +462,7 @@
ipp_job->useragent = job_params->useragent;
}
- request = _fill_job(IPP_VALIDATE_JOB, ipp_job->printer_uri, job_params);
+ request = _fill_job(IPP_VALIDATE_JOB, ipp_job->printer_uri, job_params, printer_caps);
if (ipp_job->useragent != NULL) {
httpSetDefaultField(ipp_job->http, HTTP_FIELD_USER_AGENT, ipp_job->useragent);
@@ -477,7 +502,8 @@
return result;
}
-static status_t _start_job(const ifc_print_job_t *this_p, const wprint_job_params_t *job_params) {
+static status_t _start_job(const ifc_print_job_t *this_p, const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_caps) {
LOGD("_start_job: Enter");
status_t result;
ipp_print_job_t *ipp_job;
@@ -499,7 +525,7 @@
if ((job_params->useragent != NULL) && (strlen(job_params->useragent) > 0)) {
ipp_job->useragent = job_params->useragent;
}
- request = _fill_job(IPP_PRINT_JOB, ipp_job->printer_uri, job_params);
+ request = _fill_job(IPP_PRINT_JOB, ipp_job->printer_uri, job_params, printer_caps);
if (request == NULL) {
continue;
diff --git a/jni/ipphelper/ipphelper.c b/jni/ipphelper/ipphelper.c
index 702fcd6..2da3628 100644
--- a/jni/ipphelper/ipphelper.c
+++ b/jni/ipphelper/ipphelper.c
@@ -572,7 +572,6 @@
job_state_dyn_t *job_state_dyn,
ipp_jstate_t *job_state,
const char *requesting_user) {
-
LOGD("get_JobStatus(): Enter");
static const char *const jattrs[] =
{ /* Job attributes we want */
@@ -989,14 +988,16 @@
}
static void addRollSupportedSizes(
- unsigned int width,
+ unsigned int minWidth,
+ unsigned int maxWidth,
unsigned int minHeight,
unsigned int maxHeight,
media_supported_t *media_supported,
int *sizesIdx) {
// If a supported media size fits on the roll size, add it to the list
for (int i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
- if(SupportedMediaSizes[i].WidthInMicrometers / 10 <= width
+ if (SupportedMediaSizes[i].WidthInMicrometers / 10 >= minWidth
+ && SupportedMediaSizes[i].WidthInMicrometers / 10 <= maxWidth
&& SupportedMediaSizes[i].HeightInMicrometers / 10 >= minHeight
&& SupportedMediaSizes[i].HeightInMicrometers / 10 <= maxHeight) {
addMediaIfNotDuplicate(i, sizesIdx, media_supported, SupportedMediaSizes[i].media_size);
@@ -1010,6 +1011,7 @@
printer_capabilities_t *capabilities) {
int i;
int sizes_idx = 0;
+ bool roll_supported = false;
LOGD(" Entered getMediaSupported");
media_size_t media_sizeTemp;
@@ -1017,7 +1019,7 @@
// Check for media-col-ready first
ipp_attribute_t *attrptr;
- if((attrptr =
+ if ((attrptr =
ippFindAttribute(response, "media-col-ready", IPP_TAG_BEGIN_COLLECTION)) != NULL) {
LOGD("media-col-ready found");
for (i = 0; i < ippGetCount(attrptr); i++) {
@@ -1025,6 +1027,7 @@
ipp_attribute_t *attrptr2;
media_ready_set_t mediaReadySet = {};
int minHeight = 0, maxHeight = 0;
+ int minWidth = 0, maxWidth = 0;
for (attrptr2 = ippFirstAttribute(collection);
(attrptr2 != NULL);
attrptr2 = ippNextAttribute(collection)) {
@@ -1035,7 +1038,13 @@
(attrptr3 != NULL);
attrptr3 = ippNextAttribute(collection_sec)) {
if (strcmp("x-dimension", ippGetName(attrptr3)) == 0) {
- mediaReadySet.x_dimension = ippGetInteger(attrptr3, 0);
+ if (ippGetValueTag(attrptr3) == IPP_TAG_RANGE) {
+ minWidth = ippGetRange(attrptr3, 0, &maxWidth);
+ mediaReadySet.x_dimension = minWidth;
+ } else if (ippGetValueTag(attrptr3) == IPP_TAG_INTEGER) {
+ maxWidth = ippGetInteger(attrptr3, 0);
+ mediaReadySet.x_dimension = maxWidth;
+ }
} else if (strcmp("y-dimension", ippGetName(attrptr3)) == 0) {
if (ippGetValueTag(attrptr3) == IPP_TAG_RANGE) {
minHeight = ippGetRange(attrptr3, 0, &maxHeight);
@@ -1053,8 +1062,9 @@
}
if (minHeight > 0 && maxHeight > 0
&& strstr(mediaReadySet.media_tray_tag, "roll") != NULL) {
+ roll_supported = true;
// If the source is a roll, add supported sizes that would fit on the roll
- addRollSupportedSizes(mediaReadySet.x_dimension, minHeight, maxHeight,
+ addRollSupportedSizes(minWidth, maxWidth, minHeight, maxHeight,
media_supported, &sizes_idx);
} else {
// Get the media size name from x and y dimensions
@@ -1100,6 +1110,31 @@
}
}
}
+ // Get common media which is supported by media-col-ready(roll) and media-supported
+ if (roll_supported) {
+ int supported_by_roll_and_media = 0;
+ for (int j = 0; j <= PAGE_STATUS_MAX - 1 &&
+ media_supported->media_size[j] != 0; j++) {
+ for (int k = j + 1; k <= PAGE_STATUS_MAX - 1 &&
+ media_supported->media_size[k] != 0; k++) {
+ if (media_supported->media_size[j] != 0 &&
+ media_supported->media_size[j] == media_supported->media_size[k]) {
+ media_supported->media_size[supported_by_roll_and_media] =
+ media_supported->media_size[j];
+ media_supported->idxKeywordTranTable[supported_by_roll_and_media] =
+ media_supported->idxKeywordTranTable[j];
+ supported_by_roll_and_media += 1;
+ break;
+ }
+ }
+ }
+
+ for (int j = supported_by_roll_and_media; j <= PAGE_STATUS_MAX - 1 &&
+ media_supported->media_size[j] != 0; j++) {
+ media_supported->media_size[j] = 0;
+ media_supported->idxKeywordTranTable[j] = -1;
+ }
+ }
if (sizes_idx == 0) {
LOGD("No supported media found");
}
@@ -1158,6 +1193,7 @@
media_supported_t media_supported;
for (i = 0; i <= PAGE_STATUS_MAX - 1; i++) {
media_supported.media_size[i] = 0;
+ media_supported.idxKeywordTranTable[i] = -1;
}
parse_getMediaSupported(response, &media_supported, capabilities);
@@ -1167,7 +1203,7 @@
int idx = 0;
capabilities->numSupportedMediaTypes = 0;
for (i = 0; i <= PAGE_STATUS_MAX - 1; i++) {
- if (media_supported.media_size[i] != 0) {
+ if (media_supported.media_size[i] != 0 && media_supported.idxKeywordTranTable[i] >= 0) {
capabilities->supportedMediaSizes[capabilities->numSupportedMediaSizes++] =
media_supported.media_size[i];
idx = media_supported.idxKeywordTranTable[i];
@@ -1266,6 +1302,7 @@
}
if ((attrptr = ippFindAttribute(response, "sides-supported", IPP_TAG_KEYWORD)) != NULL) {
+ capabilities->sidesSupported = 1;
for (i = 0; i < ippGetCount(attrptr); i++) {
if (strcmp(IPP_SIDES_TWO_SIDED_SHORT_EDGE, ippGetString(attrptr, i, NULL)) == 0) {
capabilities->duplex = 1;
@@ -1529,6 +1566,32 @@
}
}
}
+
+ // Determine types of print-scaling supported
+ capabilities->print_scalings_supported_count = 0;
+ if ((attrptr = ippFindAttribute(response, "print-scaling-supported", IPP_TAG_KEYWORD)) != NULL) {
+ for (i = 0; i < ippGetCount(attrptr) && i < MAX_PRINT_SCALING_COUNT; i++) {
+ capabilities->print_scalings_supported_count++;
+ strlcpy(capabilities->print_scalings_supported[i], ippGetString(attrptr, i, NULL),
+ sizeof(capabilities->print_scalings_supported[i]));
+ }
+ } else {
+ LOGD("print-scaling-supported not found");
+ }
+
+ memset(capabilities->print_scaling_default, '\0', sizeof(capabilities->print_scaling_default));
+ if ((attrptr = ippFindAttribute(response, "print-scaling-default", IPP_TAG_KEYWORD)) != NULL) {
+ strlcpy(capabilities->print_scaling_default, ippGetString(attrptr, 0, NULL),
+ sizeof(capabilities->print_scaling_default));
+ } else {
+ LOGD("print-scaling-default not found");
+ }
+
+ if ((attrptr = ippFindAttribute(response, "job-pages-per-set-supported",
+ IPP_TAG_BOOLEAN)) != NULL && ippGetBoolean(attrptr, 0)) {
+ capabilities->jobPagesPerSetSupported = 1;
+ }
+
debuglist_printerCapabilities(capabilities);
}
@@ -1587,6 +1650,11 @@
LOGD("ippVersionMinor: %d", capabilities->ippVersionMinor);
LOGD("strip height: %d", capabilities->stripHeight);
LOGD("faceDownTray: %d", capabilities->faceDownTray);
+ for (int i = 0; i < capabilities->print_scalings_supported_count; i++) {
+ LOGD("print-scaling-supported (%d): %s", i, capabilities->print_scalings_supported[i]);
+ }
+ LOGD("print_scaling_default: %s",capabilities->print_scaling_default);
+ LOGD("jobPagesPerSetSupported: %d", capabilities->jobPagesPerSetSupported);
}
void debuglist_printerStatus(printer_state_dyn_t *printer_state_dyn) {
diff --git a/jni/ipphelper/ippstatus_capabilities.c b/jni/ipphelper/ippstatus_capabilities.c
index 6bd821f..48fa143 100644
--- a/jni/ipphelper/ippstatus_capabilities.c
+++ b/jni/ipphelper/ippstatus_capabilities.c
@@ -68,7 +68,10 @@
"pwg-raster-document-sheet-back",
"document-format-details-supported",
"media-ready",
- "media-col-ready"
+ "media-col-ready",
+ "print-scaling-supported",
+ "print-scaling-default",
+ "job-pages-per-set-supported"
};
static void _init(const ifc_printer_capabilities_t *this_p,
diff --git a/jni/lib/lib_wprint.c b/jni/lib/lib_wprint.c
index ebdec13..ac39a81 100755
--- a/jni/lib/lib_wprint.c
+++ b/jni/lib/lib_wprint.c
@@ -103,7 +103,7 @@
JOB_STATE_COMPLETED, // print job completed successfully, waiting to be freed
JOB_STATE_ERROR, // job could not be run due to error
JOB_STATE_CORRUPTED, // job could not be run due to error
-
+ JOB_STATE_BAD_CERTIFICATE, // server gave an unexpected ssl certificate
NUM_JOB_STATES
} _job_state_t;
@@ -197,6 +197,10 @@
static _io_plugin_t _io_plugins[2];
+static volatile bool stop_run = false;
+
+static printer_capabilities_t g_printer_caps = {0};
+
char g_osName[MAX_ID_STRING_LENGTH + 1] = {0};
char g_appName[MAX_ID_STRING_LENGTH + 1] = {0};
char g_appVersion[MAX_ID_STRING_LENGTH + 1] = {0};
@@ -883,6 +887,7 @@
int i;
status_t job_result;
int corrupted = 0;
+ printer_capabilities_t printer_caps;
while (OK == msgQReceive(_msgQ, (char *) &msg, sizeof(msg), WAIT_FOREVER)) {
if (msg.id == MSG_RUN_JOB) {
@@ -926,8 +931,9 @@
if ((jq->status_ifc != NULL) && (jq->status_ifc->get_status != NULL)) {
int retry = 0;
bool idle = false;
+ bool bad_certificate = false;
printer_state_dyn_t printer_state;
- while (!idle) {
+ while (!idle && !stop_run) {
print_status_t status;
jq->status_ifc->get_status(jq->status_ifc, &printer_state);
status = printer_state.printer_status & ~PRINTER_IDLE_BIT;
@@ -953,7 +959,7 @@
jq->blocked_reasons = BLOCKED_REASON_UNABLE_TO_CONNECT;
} else {
LOGD("%s: Bad certificate", __func__);
- jq->blocked_reasons = BLOCKED_REASON_BAD_CERTIFICATE;
+ bad_certificate = true;
}
} else if (printer_state.printer_status & PRINTER_IDLE_BIT) {
LOGD("%s: printer blocked but appears to be in an idle state. "
@@ -996,9 +1002,16 @@
if (jq->job_params.cancelled) {
job_result = CANCELLED;
+ } else if (bad_certificate) {
+ job_result = BAD_CERTIFICATE;
} else {
- job_result = (((printer_state.printer_status & ~PRINTER_IDLE_BIT) ==
- PRINT_STATUS_IDLE) ? OK : ERROR);
+ if (stop_run) {
+ jq->job_state = JOB_STATE_ERROR;
+ job_result = ERROR;
+ } else {
+ job_result = (((printer_state.printer_status & ~PRINTER_IDLE_BIT) ==
+ PRINT_STATUS_IDLE) ? OK : ERROR);
+ }
}
}
@@ -1027,14 +1040,20 @@
jq->cb_fn(job_handle, (void *) &cb_param);
}
+ memcpy(&printer_caps, &g_printer_caps, sizeof(printer_capabilities_t));
+
jq->job_params.page_num = -1;
if (job_result == OK) {
if (jq->print_ifc != NULL) {
LOGD("_job_thread: Calling validate_job");
if (jq->print_ifc->validate_job != NULL) {
- job_result = jq->print_ifc->validate_job(jq->print_ifc, &jq->job_params);
+ job_result = jq->print_ifc->validate_job(jq->print_ifc, &jq->job_params,
+ &printer_caps);
}
-
+ if (!_is_certificate_allowed(jq)) {
+ LOGD("_job_thread: bad certificate found at validate job");
+ job_result = BAD_CERTIFICATE;
+ }
/* PDF format plugin's start_job and end_job are to be called for each copy,
* inside the for-loop for num_copies.
*/
@@ -1042,7 +1061,7 @@
// Do not call start_job unless validate_job returned OK
if ((job_result == OK) && (jq->print_ifc->start_job != NULL) &&
(strcmp(jq->job_params.print_format, PRINT_FORMAT_PDF) != 0)) {
- jq->print_ifc->start_job(jq->print_ifc, &jq->job_params);
+ jq->print_ifc->start_job(jq->print_ifc, &jq->job_params, &printer_caps);
}
}
@@ -1072,7 +1091,7 @@
bool pdf_printed = false;
if (jq->print_ifc->start_job != NULL &&
(strcmp(jq->job_params.print_format, PRINT_FORMAT_PDF) == 0)) {
- jq->print_ifc->start_job(jq->print_ifc, &jq->job_params);
+ jq->print_ifc->start_job(jq->print_ifc, &jq->job_params, &printer_caps);
}
per_copy_page_num = 0;
@@ -1107,6 +1126,13 @@
jq->job_params.last_page = false;
}
+ bool printBlankPage = (strcmp(jq->job_params.print_format,
+ PRINT_FORMAT_PCLM) == 0) ? wprintBlankPageForPclm(
+ &jq->job_params, &printer_caps) : wprintBlankPageForPwg(
+ &jq->job_params, &printer_caps);
+
+ printBlankPage &= (jq->plugin->print_blank_page != NULL);
+
if (strlen(page.filename) > 0) {
per_copy_page_num++;
{
@@ -1126,7 +1152,7 @@
jq->job_params.copy_num = (i + 1);
jq->job_params.copy_page_num = page.page_num;
- jq->job_params.page_backside = !(per_copy_page_num & 0x1);
+ jq->job_params.page_backside = !(page.page_num & 0x1);
jq->job_params.page_corrupted = (page.corrupted ? 1 : 0);
jq->job_params.page_printing = true;
_unlock();
@@ -1134,6 +1160,14 @@
if (!page.corrupted) {
LOGD("_job_thread(): page not corrupt, calling plugin's print_page"
" function for page #%d", page.page_num);
+
+ // make sure we always print an even number of pages in duplex jobs
+ if ((page.page_num == jq->job_params.job_pages_per_set) &&
+ !(jq->job_params.face_down_tray) && printBlankPage) {
+ jq->plugin->print_blank_page(job_handle, &(jq->job_params),
+ jq->mime_type, page.filename);
+ }
+
if (strcmp(jq->job_params.print_format, PRINT_FORMAT_PDF) != 0) {
job_result = jq->plugin->print_page(&(jq->job_params),
jq->mime_type,
@@ -1152,7 +1186,8 @@
job_result = CORRUPT;
if ((jq->job_params.duplex != DUPLEX_MODE_NONE) &&
(jq->plugin->print_blank_page != NULL)) {
- jq->plugin->print_blank_page(job_handle, &(jq->job_params));
+ jq->plugin->print_blank_page(job_handle, &(jq->job_params),
+ jq->mime_type, page.filename);
}
}
_lock();
@@ -1171,11 +1206,11 @@
}
// make sure we always print an even number of pages in duplex jobs
- if (page.last_page && (jq->job_params.duplex != DUPLEX_MODE_NONE)
- && !(jq->job_params.page_backside)
- && (jq->plugin->print_blank_page != NULL)) {
+ if (page.last_page && (jq->job_params.face_down_tray) &&
+ !(jq->job_params.page_backside) && printBlankPage) {
_unlock();
- jq->plugin->print_blank_page(job_handle, &(jq->job_params));
+ jq->plugin->print_blank_page(job_handle, &(jq->job_params),
+ jq->mime_type, page.filename);
_lock();
}
@@ -1252,7 +1287,7 @@
if ((jq->job_params.duplex != DUPLEX_MODE_NONE)
&& (jq->plugin->print_blank_page != NULL)) {
jq->plugin->print_blank_page(job_handle,
- &(jq->job_params));
+ &(jq->job_params), jq->mime_type, page.filename);
}
_lock();
@@ -1265,9 +1300,9 @@
// if we started the job end it
if (jq->job_params.page_num >= 0) {
// if the job was cancelled without sending anything through, print a blank sheet
- if ((jq->job_params.page_num == 0)
- && (jq->plugin->print_blank_page != NULL)) {
- jq->plugin->print_blank_page(job_handle, &(jq->job_params));
+ if ((jq->job_params.page_num == 0) && (jq->plugin->print_blank_page != NULL)) {
+ jq->plugin->print_blank_page(job_handle, &(jq->job_params), jq->mime_type,
+ page.filename);
}
if (jq->plugin->end_job != NULL) {
jq->plugin->end_job(&(jq->job_params));
@@ -1369,6 +1404,11 @@
jq->job_state = JOB_STATE_CORRUPTED;
jq->blocked_reasons = 0;
break;
+ case BAD_CERTIFICATE:
+ LOGD("_job_thread(): BAD_CERTIFICATE");
+ jq->job_state = JOB_STATE_BAD_CERTIFICATE;
+ jq->blocked_reasons = 0;
+ break;
case ERROR:
default:
LOGE("_job_thread(): ERROR plugin->start_job(%ld): %s => %s", job_handle,
@@ -1419,6 +1459,7 @@
_job_tid = pthread_self();
result = OK;
+ stop_run = false;
sigfillset(&allsig);
#if CHECK_PTHREAD_SIGMASK_STATUS
result = pthread_sigmask(SIG_SETMASK, &allsig, &oldsig);
@@ -1453,6 +1494,7 @@
* Waits for the job thread to reach a stopped state
*/
static int _stop_thread(void) {
+ stop_run = true;
if (!pthread_equal(_job_tid, pthread_self())) {
pthread_join(_job_tid, 0);
_job_tid = pthread_self();
@@ -1676,6 +1718,8 @@
printer_cap->canPrintPWG);
if (result == OK) {
+ memcpy(&g_printer_caps, printer_cap, sizeof(printer_capabilities_t));
+
LOGD("\tmake: %s", printer_cap->make);
LOGD("\thas color: %d", printer_cap->color);
LOGD("\tcan duplex: %d", printer_cap->duplex);
@@ -1703,7 +1747,7 @@
/*
* Returns a preferred print format supported by the printer
*/
-static char *_get_print_format(const char *mime_type, const wprint_job_params_t *job_params,
+char *_get_print_format(const char *mime_type, const wprint_job_params_t *job_params,
const printer_capabilities_t *cap) {
char *print_format = NULL;
@@ -1747,10 +1791,10 @@
.duplex = DUPLEX_MODE_NONE, .dry_time = DUPLEX_DRY_TIME_NORMAL,
.color_space = COLOR_SPACE_COLOR, .media_tray = TRAY_SRC_AUTO_SELECT,
.pixel_units = DEFAULT_RESOLUTION, .render_flags = 0, .num_copies =1,
- .borderless = false, .cancelled = false, .renderInReverseOrder = false,
+ .borderless = false, .cancelled = false, .face_down_tray = false,
.ipp_1_0_supported = false, .ipp_2_0_supported = false, .epcl_ipp_supported = false,
.strip_height = STRIPE_HEIGHT, .docCategory = {0},
- .copies_supported = false};
+ .copies_supported = false, .preserve_scaling = false};
if (job_params == NULL) return result;
@@ -1883,11 +1927,7 @@
LOGD("wprintGetFinalJobParams: Duplex is on and device needs back page rotated.");
}
- if ((job_params->duplex == DUPLEX_MODE_NONE) && !printer_cap->faceDownTray) {
- job_params->renderInReverseOrder = true;
- } else {
- job_params->renderInReverseOrder = false;
- }
+ job_params->face_down_tray = printer_cap->faceDownTray;
if (job_params->render_flags & RENDER_FLAG_AUTO_SCALE) {
job_params->render_flags |= AUTO_SCALE_RENDER_FLAGS;
@@ -2196,7 +2236,7 @@
if (jq) {
LOGI("received cancel request");
- // send a dummy page in case we're waiting on the msgQ page receive
+ // send an empty page in case we're waiting on the msgQ page receive
if ((jq->job_state == JOB_STATE_RUNNING) || (jq->job_state == JOB_STATE_BLOCKED)) {
bool enableTimeout = true;
jq->cancel_ok = true;
@@ -2291,6 +2331,7 @@
sem_destroy(&_job_end_wait_sem);
sem_destroy(&_job_start_wait_sem);
+ pthread_mutex_destroy(&_q_lock);
}
return OK;
@@ -2311,3 +2352,17 @@
LOGI("App Name: '%s', Version: '%s', OS: '%s'", g_appName, g_appVersion, g_osName);
}
+
+bool wprintBlankPageForPclm(const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_cap) {
+ return ((job_params->job_pages_per_set % 2) &&
+ ((job_params->num_copies > 1 && printer_cap->sidesSupported) ||
+ (job_params->num_copies == 1)) && (job_params->duplex != DUPLEX_MODE_NONE));
+}
+
+bool wprintBlankPageForPwg(const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_cap) {
+ return ((job_params->job_pages_per_set % 2) && (job_params->duplex != DUPLEX_MODE_NONE) &&
+ !(printer_cap->jobPagesPerSetSupported &&
+ strcmp(job_params->print_format, PRINT_FORMAT_PWG) == 0));
+}
diff --git a/jni/lib/printable_area.c b/jni/lib/printable_area.c
index 81534b7..701f34a 100755
--- a/jni/lib/printable_area.c
+++ b/jni/lib/printable_area.c
@@ -47,16 +47,30 @@
if (fabsf(job_params->source_width - job_params->page_width) < PAGE_SIZE_EPSILON &&
fabsf(job_params->source_height - job_params->page_height) < PAGE_SIZE_EPSILON) {
top_margin = left_margin = right_margin = bottom_margin = 0.0f;
+ job_params->preserve_scaling = true;
}
// don't adjust for margins if job is PCLm. dimensions of image will not
// match (will be bigger than) the dimensions of the page size and a corrupt image will render
// in genPCLm
if (job_params->pcl_type == PCLm) {
- job_params->printable_area_width = (unsigned int) _MI_TO_PIXELS(
- job_params->page_width * 1000, job_params->pixel_units);
- job_params->printable_area_height = (unsigned int) _MI_TO_PIXELS(
- job_params->page_height * 1000, job_params->pixel_units);
+ if (job_params->borderless) {
+ job_params->printable_area_width = (unsigned int) _MI_TO_PIXELS(
+ job_params->page_width * 1000, job_params->pixel_units);
+ job_params->printable_area_height = (unsigned int) _MI_TO_PIXELS(
+ job_params->page_height * 1000, job_params->pixel_units);
+ } else {
+ job_params->printable_area_width =
+ (unsigned int) _MI_TO_PIXELS(job_params->page_width * 1000,
+ job_params->pixel_units)
+ - floorf(left_margin * (float) job_params->pixel_units)
+ - floorf(right_margin * (float) job_params->pixel_units);
+ job_params->printable_area_height =
+ (unsigned int) _MI_TO_PIXELS(job_params->page_height * 1000,
+ job_params->pixel_units)
+ - floorf(top_margin * (float) job_params->pixel_units)
+ - floorf(bottom_margin * (float) job_params->pixel_units);
+ }
} else {
job_params->printable_area_width = (unsigned int) floorf(((job_params->page_width -
(left_margin + right_margin)) * (float)job_params->pixel_units));
diff --git a/jni/lib/printer.c b/jni/lib/printer.c
index 99aadf4..625d549 100644
--- a/jni/lib/printer.c
+++ b/jni/lib/printer.c
@@ -77,7 +77,8 @@
}
}
-static int _start_job(const ifc_print_job_t *this_p, const wprint_job_params_t *job_params) {
+static int _start_job(const ifc_print_job_t *this_p, const wprint_job_params_t *job_params,
+ const printer_capabilities_t *printer_caps) {
_print_job_t *print_job = IMPL(_print_job_t, ifc, this_p);
if (print_job) {
diff --git a/jni/lib/wprintJNI.c b/jni/lib/wprintJNI.c
index 1a3e757..f0d2d0d 100755
--- a/jni/lib/wprintJNI.c
+++ b/jni/lib/wprintJNI.c
@@ -20,6 +20,8 @@
#include "lib_wprint.h"
#include "wprint_debug.h"
#include <errno.h>
+#include <bits/strcasecmp.h>
+#include <string.h>
#include "../plugins/wprint_mupdf.h"
#define TAG "wprintJNI"
@@ -63,6 +65,8 @@
static jfieldID _LocalJobParamsField__pdf_render_resolution;
static jfieldID _LocalJobParamsField__source_width;
static jfieldID _LocalJobParamsField__source_height;
+static jfieldID _LocalJobParamsField__shared_photo;
+static jfieldID _LocalJobParamsField__preserve_scaling;
static jclass _LocalPrinterCapabilitiesClass;
static jfieldID _LocalPrinterCapabilitiesField__name;
@@ -417,8 +421,8 @@
// print forward direction if printer prints pages face down; otherwise print backward
// NOTE: last page is sent from calling function
- if (printer_cap->faceDownTray || duplex) {
- LOGD("_print_pdf_pages(), pages print face down or duplex, printing in normal order");
+ if (printer_cap->faceDownTray) {
+ LOGD("_print_pdf_pages(), pages print face down, printing in normal order");
page_index = 0;
while (page_index < num_pages) {
LOGD("_print_pdf_pages(), PRINTING PDF: %d", *(pages_ary + page_index));
@@ -497,6 +501,10 @@
"Z");
_LocalJobParamsField__fill_page = (*env)->GetFieldID(env, _LocalJobParamsClass, "fill_page",
"Z");
+ _LocalJobParamsField__shared_photo = (*env)->GetFieldID(env, _LocalJobParamsClass,
+ "shared_photo", "Z");
+ _LocalJobParamsField__preserve_scaling = (*env)->GetFieldID(env, _LocalJobParamsClass,
+ "preserve_scaling", "Z");
_LocalJobParamsField__auto_rotate = (*env)->GetFieldID(env, _LocalJobParamsClass, "auto_rotate",
"Z");
_LocalJobParamsField__portrait_mode = (*env)->GetFieldID(env, _LocalJobParamsClass,
@@ -750,7 +758,6 @@
_PrintServiceStringsField__BLOCKED_REASON__PRINTER_NMS_RESET = (*env)->GetStaticFieldID(env,
_PrintServiceStringsClass, "BLOCKED_REASON__PRINTER_NMS_RESET", "Ljava/lang/String;");
-
_PrintServiceStringsField__ALIGNMENT__CENTER = (*env)->GetStaticFieldID(
env, _PrintServiceStringsClass, "ALIGN_CENTER", "I");
_PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL = (*env)->GetStaticFieldID(
@@ -966,6 +973,8 @@
env, javaJobParams, _LocalJobParamsField__source_height);
wprintJobParams->source_width = (float) (*env)->GetFloatField(
env, javaJobParams, _LocalJobParamsField__source_width);
+ wprintJobParams->preserve_scaling = (bool) (*env)->GetBooleanField(env, javaJobParams,
+ _LocalJobParamsField__preserve_scaling);
if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__portrait_mode)) {
wprintJobParams->render_flags |= RENDER_FLAG_PORTRAIT_MODE;
@@ -1119,6 +1128,8 @@
(wprintJobParams->render_flags & RENDER_FLAG_PORTRAIT_MODE) != 0));
(*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__landscape_mode, (jboolean) (
(wprintJobParams->render_flags & RENDER_FLAG_LANDSCAPE_MODE) != 0));
+ (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__preserve_scaling,
+ (jboolean) (wprintJobParams->preserve_scaling));
// update the printable area & DPI information
(*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__print_resolution,
@@ -1570,6 +1581,11 @@
env, _PrintServiceStringsClass,
_PrintServiceStringsField__JOB_DONE_CORRUPT);
break;
+ case BAD_CERTIFICATE:
+ jStr = (jstring) (*env)->GetStaticObjectField(
+ env, _PrintServiceStringsClass,
+ _PrintServiceStringsField__JOB_DONE_BAD_CERTIFICATE);
+ break;
default:
jStr = (jstring) (*env)->GetStaticObjectField(
env, _PrintServiceStringsClass,
@@ -1819,6 +1835,7 @@
int pdf_pages_ary[len];
int pages_ary[len][MAX_NUM_PAGES];
+ const char *print_format = _get_print_format(mimeTypeStr, ¶ms, &caps);
if (hasFiles) {
result = OK;
@@ -1860,6 +1877,61 @@
}
(*env)->ReleaseStringUTFChars(env, page, pageStr);
+
+ bool shared_photo = (*env)->GetBooleanField(env, jobParams,
+ _LocalJobParamsField__shared_photo);
+ bool preserve_scaling = (*env)->GetBooleanField(env, jobParams,
+ _LocalJobParamsField__preserve_scaling);
+ LOGD("setting print-scaling job param");
+ LOGD("shared_photo = %d", shared_photo);
+ LOGD("preserve_scaling = %d", preserve_scaling);
+
+ char print_scaling[MAX_PRINT_SCALING_LENGTH] = "";
+ if (strcmp(print_format, PRINT_FORMAT_PDF) == 0) {
+ LOGD("PDF pass-through");
+ bool is_photo = strcasecmp(params.docCategory, "Photo") == 0;
+ if ((is_photo && shared_photo) || preserve_scaling) {
+ for (int i = 0; i < caps.print_scalings_supported_count; i++) {
+ if (strcmp(caps.print_scalings_supported[i], "none") == 0) {
+ strlcpy(print_scaling, "none", sizeof(print_scaling));
+ break;
+ }
+ }
+ } else {
+ bool auto_supported = false;
+ for (int i = 0; i < caps.print_scalings_supported_count; i++) {
+ if (strcmp(caps.print_scalings_supported[i], "auto") == 0) {
+ strlcpy(print_scaling, "auto", sizeof(print_scaling));
+ auto_supported = true;
+ break;
+ }
+ }
+ if (!auto_supported) {
+ if (strcmp(caps.print_scaling_default, "") != 0) {
+ strlcpy(print_scaling, caps.print_scaling_default,
+ sizeof(caps.print_scaling_default));
+ } else {
+ strlcpy(print_scaling, "fit", sizeof(print_scaling));
+ }
+ }
+ }
+ } else {
+ LOGD("PCLm / PWG-Raster");
+ for (int i = 0; i < caps.print_scalings_supported_count; i++) {
+ if (strcmp(caps.print_scalings_supported[i], "none") == 0) {
+ strlcpy(print_scaling, "none", sizeof(print_scaling));
+ break;
+ }
+ }
+ }
+ LOGD("setting print-scaling value = %s", print_scaling);
+ strlcpy(params.print_scaling, print_scaling, sizeof(params.print_scaling));
+
+ params.job_pages_per_set = 0;
+ for (int i = 0; i < len; i++) {
+ params.job_pages_per_set += pdf_pages_ary[i];
+ }
+
const char *jobDebugDirStr = NULL;
if (jobDebugDir != NULL) {
jobDebugDirStr = (*env)->GetStringUTFChars(env, jobDebugDir, NULL);
@@ -1879,7 +1951,7 @@
job_handle = (wJob_t) result;
// register job handle with service
- if (caps.faceDownTray || params.duplex) {
+ if (caps.faceDownTray) {
index = 0;
incrementor = 1;
} else {
diff --git a/jni/plugins/lib_pwg.c b/jni/plugins/lib_pwg.c
index 8e3e525..54d9340 100644
--- a/jni/plugins/lib_pwg.c
+++ b/jni/plugins/lib_pwg.c
@@ -319,12 +319,14 @@
* Allocate and fill a blank page of PackBits data. Writes size into buffer_size. The buffer
* must be free'd by the caller.
*/
-unsigned char *_generate_blank_data(int pixel_width, int pixel_height, uint8 monochrome, size_t *buffer_size) {
+unsigned char *_generate_blank_data(int pixel_width, int pixel_height,
+ uint8 monochrome, size_t *buffer_size) {
if (pixel_width == 0 || pixel_height == 0) return NULL;
/* PWG Raster's PackBits-like algorithm allows for a maximum of:
* 256 repeating rows and is encoded using a single octet containing (count - 1)
- * 128 repeating color value and is run length encoded using a single octet containing (count - 1)
+ * 128 repeating color value and is run length encoded using a single octet
+ * containing (count - 1)
*/
int rows_full = pixel_height / 256;
int columns_full = pixel_width / 128;
@@ -371,8 +373,9 @@
size_t buffer_size;
unsigned char *buffer;
- _start_page(job_info, header_pwg.cupsWidth, header_pwg.cupsHeight);
- buffer = _generate_blank_data(header_pwg.cupsWidth, header_pwg.cupsHeight, job_info->monochrome, &buffer_size);
+ _start_page(job_info, job_info->pixel_width, job_info->pixel_height);
+ buffer = _generate_blank_data(job_info->pixel_width, job_info->pixel_height,
+ job_info->monochrome, &buffer_size);
if (buffer == NULL) {
return ERROR;
} else {
diff --git a/jni/plugins/plugin_pcl.c b/jni/plugins/plugin_pcl.c
index 4170173..6433cd7 100755
--- a/jni/plugins/plugin_pcl.c
+++ b/jni/plugins/plugin_pcl.c
@@ -32,6 +32,7 @@
#include <pthread.h>
#include <semaphore.h>
+#include <string.h>
#define MAX_SEND_BUFFS (BUFFERED_ROWS / STRIPE_HEIGHT)
@@ -273,10 +274,94 @@
return ERROR;
}
+static status_t _setup_image_info(wprint_job_params_t *job_params, wprint_image_info_t *image_info,
+ const char *mime_type, const char *pathname) {
+ FILE *imgfile;
+ status_t result;
+ plugin_data_t *priv;
+
+ priv = (plugin_data_t *) job_params->plugin_data;
+ if (priv == NULL) return ERROR;
+
+ if (pathname == NULL) {
+ LOGE("_setup_image_info(): cannot print file with NULL name");
+ return ERROR;
+ }
+
+ if (!strlen(pathname)) {
+ LOGE("_setup_image_info(): filename was empty");
+ return ERROR;
+ }
+
+ imgfile = fopen(pathname, "r");
+ if (imgfile == NULL) {
+ LOGE("_setup_image_info(): could not open %s", pathname);
+ return CORRUPT;
+ }
+
+ LOGD("_setup_image_info(): fopen succeeded on %s", pathname);
+ wprint_image_setup(image_info, mime_type, priv->job_info.wprint_ifc,
+ job_params->pixel_units, job_params->pdf_render_resolution);
+ wprint_image_init(image_info, pathname, job_params->page_num);
+
+ // get the image_info of the input file of specified MIME type
+ if ((result = wprint_image_get_info(imgfile, image_info)) == OK) {
+ wprint_rotation_t rotation = ROT_0;
+
+ if ((job_params->render_flags & RENDER_FLAG_PORTRAIT_MODE) != 0) {
+ LOGI("_setup_image_info(): portrait mode");
+ rotation = ROT_0;
+ } else if ((job_params->render_flags & RENDER_FLAG_LANDSCAPE_MODE) != 0) {
+ LOGI("_setup_image_info(): landscape mode");
+ rotation = ROT_90;
+ } else if (wprint_image_is_landscape(image_info) &&
+ ((job_params->render_flags & RENDER_FLAG_AUTO_ROTATE) != 0)) {
+ LOGI("_setup_image_info(): auto mode");
+ rotation = ROT_90;
+ }
+
+ if ((job_params->render_flags & RENDER_FLAG_CENTER_ON_ORIENTATION) != 0) {
+ job_params->render_flags &= ~(RENDER_FLAG_CENTER_HORIZONTAL |
+ RENDER_FLAG_CENTER_VERTICAL);
+ job_params->render_flags |= ((rotation == ROT_0) ? RENDER_FLAG_CENTER_HORIZONTAL
+ : RENDER_FLAG_CENTER_VERTICAL);
+ }
+
+ if ((job_params->duplex == DUPLEX_MODE_BOOK) &&
+ (job_params->page_backside) &&
+ ((job_params->render_flags & RENDER_FLAG_ROTATE_BACK_PAGE) != 0) &&
+ ((job_params->render_flags & RENDER_FLAG_BACK_PAGE_PREROTATED) == 0)) {
+ rotation = ((rotation == ROT_0) ? ROT_180 : ROT_270);
+ }
+ LOGI("_setup_image_info(): rotation = %d", rotation);
+
+ int image_padding = PAD_PRINT;
+ switch (job_params->pcl_type) {
+ case PCLm:
+ case PCLPWG:
+ image_padding = PAD_ALL;
+ break;
+ default:
+ break;
+ }
+
+ wprint_image_set_output_properties(image_info, rotation,
+ job_params->printable_area_width, job_params->printable_area_height,
+ job_params->print_top_margin, job_params->print_left_margin,
+ job_params->print_right_margin, job_params->print_bottom_margin,
+ job_params->render_flags, job_params->strip_height, MAX_SEND_BUFFS,
+ image_padding);
+ } else {
+ LOGE("_setup_image_info(): file does not appear to be valid");
+ result = CORRUPT;
+ }
+ fclose(imgfile);
+ return result;
+}
+
static status_t _print_page(wprint_job_params_t *job_params, const char *mime_type,
const char *pathname) {
wprint_image_info_t *image_info;
- FILE *imgfile;
status_t result;
int num_rows, height, image_row;
int blank_data;
@@ -287,7 +372,6 @@
int nbytes;
plugin_data_t *priv;
msgQ_msg_t msg;
- int image_padding = PAD_PRINT;
if (job_params == NULL) return ERROR;
@@ -295,200 +379,124 @@
if (priv == NULL) return ERROR;
- switch (job_params->pcl_type) {
- case PCLm:
- case PCLPWG:
- image_padding = PAD_ALL;
- break;
- default:
- break;
- }
+ image_info = malloc(sizeof(wprint_image_info_t));
- if (pathname == NULL) {
- LOGE("_print_page(): cannot print file with NULL name");
- msg.param.end_page.page = -1;
- msg.param.end_page.count = 0;
- result = ERROR;
- } else if (strlen(pathname)) {
- image_info = malloc(sizeof(wprint_image_info_t));
- if (image_info == NULL) return ERROR;
+ if (image_info == NULL) return ERROR;
- imgfile = fopen(pathname, "r");
- if (imgfile) {
- LOGD("_print_page(): fopen succeeded on %s", pathname);
- wprint_image_setup(image_info, mime_type, priv->job_info.wprint_ifc,
- job_params->pixel_units, job_params->pdf_render_resolution);
- wprint_image_init(image_info, pathname, job_params->page_num);
+ if ((result = _setup_image_info(job_params, image_info, mime_type, pathname)) == OK) {
+ // allocate memory for a stripe of data
+ for (i = 0; i < MAX_SEND_BUFFS; i++) {
+ buff_pool[i] = NULL;
+ }
- // get the image_info of the input file of specified MIME type
- if ((result = wprint_image_get_info(imgfile, image_info)) == OK) {
- wprint_rotation_t rotation = ROT_0;
+ blank_data = MAX_SEND_BUFFS;
+ buff_size = wprint_image_get_output_buff_size(image_info);
+ for (i = 0; i < MAX_SEND_BUFFS; i++) {
+ buff_pool[i] = malloc(buff_size);
+ if (buff_pool[i] == NULL) {
+ break;
+ }
+ memset(buff_pool[i], 0xff, buff_size);
+ }
- if ((job_params->render_flags & RENDER_FLAG_PORTRAIT_MODE) != 0) {
- LOGI("_print_page(): portrait mode");
- rotation = ROT_0;
- } else if ((job_params->render_flags & RENDER_FLAG_LANDSCAPE_MODE) != 0) {
- LOGI("_print_page(): landscape mode");
- rotation = ROT_90;
- } else if (wprint_image_is_landscape(image_info) &&
- ((job_params->render_flags & RENDER_FLAG_AUTO_ROTATE) != 0)) {
- LOGI("_print_page(): auto mode");
- rotation = ROT_90;
+ if (i == MAX_SEND_BUFFS) {
+ msg.id = MSG_START_PAGE;
+ msg.param.start_page.extra_margin = ((job_params->duplex != DUPLEX_MODE_NONE) &&
+ ((job_params->page_num & 0x1) == 0)) ? job_params->page_bottom_margin : 0.0f;
+ msg.param.start_page.width = wprint_image_get_width(image_info);
+ msg.param.start_page.height = wprint_image_get_height(image_info);
+ priv->job_info.num_components = image_info->num_components;
+ priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg, sizeof(msgQ_msg_t),
+ NO_WAIT, MSG_Q_FIFO);
+
+ msg.id = MSG_SEND;
+ msg.param.send.bytes_per_row = BYTES_PER_PIXEL(wprint_image_get_width(image_info));
+
+ // send blank rows for any offset
+ buff_index = 0;
+ num_rows = wprint_image_get_height(image_info);
+ image_row = 0;
+
+ // decode and render each stripe into PCL3 raster format
+ while ((result != ERROR) && (num_rows > 0)) {
+ if (priv->pcl_ifc->canCancelMidPage() && job_params->cancelled) {
+ break;
}
+ sem_wait(&priv->buffs_sem);
- if ((job_params->render_flags & RENDER_FLAG_CENTER_ON_ORIENTATION) != 0) {
- job_params->render_flags &= ~(RENDER_FLAG_CENTER_HORIZONTAL |
- RENDER_FLAG_CENTER_VERTICAL);
- job_params->render_flags |= ((rotation == ROT_0) ? RENDER_FLAG_CENTER_HORIZONTAL
- : RENDER_FLAG_CENTER_VERTICAL);
- }
+ buff = buff_pool[buff_index];
+ buff_index = ((buff_index + 1) % MAX_SEND_BUFFS);
- if ((job_params->duplex == DUPLEX_MODE_BOOK) &&
- (job_params->page_backside) &&
- ((job_params->render_flags & RENDER_FLAG_ROTATE_BACK_PAGE) != 0) &&
- ((job_params->render_flags & RENDER_FLAG_BACK_PAGE_PREROTATED) == 0)) {
- rotation = ((rotation == ROT_0) ? ROT_180 : ROT_270);
- }
- LOGI("_print_page(): rotation = %d", rotation);
+ height = MIN(num_rows, job_params->strip_height);
+ if (!job_params->cancelled) {
+ nbytes = wprint_image_decode_stripe(image_info, image_row, &height,
+ (unsigned char *) buff);
- wprint_image_set_output_properties(image_info, rotation,
- job_params->printable_area_width, job_params->printable_area_height,
- job_params->print_top_margin, job_params->print_left_margin,
- job_params->print_right_margin, job_params->print_bottom_margin,
- job_params->render_flags, job_params->strip_height, MAX_SEND_BUFFS,
- image_padding);
-
- // allocate memory for a stripe of data
- for (i = 0; i < MAX_SEND_BUFFS; i++) {
- buff_pool[i] = NULL;
- }
-
- blank_data = MAX_SEND_BUFFS;
- buff_size = wprint_image_get_output_buff_size(image_info);
- for (i = 0; i < MAX_SEND_BUFFS; i++) {
- buff_pool[i] = malloc(buff_size);
- if (buff_pool[i] == NULL) {
- break;
+ if (blank_data > 0) {
+ blank_data--;
}
- memset(buff_pool[i], 0xff, buff_size);
+ } else if (blank_data < MAX_SEND_BUFFS) {
+ nbytes = buff_size;
+ memset(buff, 0xff, buff_size);
+ blank_data++;
}
- if (i == MAX_SEND_BUFFS) {
- msg.id = MSG_START_PAGE;
- msg.param.start_page.extra_margin = ((job_params->duplex !=
- DUPLEX_MODE_NONE) &&
- ((job_params->page_num & 0x1) == 0))
- ? job_params->page_bottom_margin : 0.0f;
- msg.param.start_page.width = wprint_image_get_width(image_info);
- msg.param.start_page.height = wprint_image_get_height(image_info);
- priv->job_info.num_components = image_info->num_components;
- priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg,
+ if (nbytes > 0) {
+ msg.param.send.buffer = buff;
+ msg.param.send.start_row = image_row;
+ msg.param.send.num_rows = height;
+
+ result = priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg,
sizeof(msgQ_msg_t), NO_WAIT, MSG_Q_FIFO);
-
- msg.id = MSG_SEND;
- msg.param.send.bytes_per_row = BYTES_PER_PIXEL(wprint_image_get_width(
- image_info));
-
- // send blank rows for any offset
- buff_index = 0;
- num_rows = wprint_image_get_height(image_info);
- image_row = 0;
-
- // decode and render each stripe into PCL3 raster format
- while ((result != ERROR) && (num_rows > 0)) {
- if (priv->pcl_ifc->canCancelMidPage() && job_params->cancelled) {
- break;
- }
- sem_wait(&priv->buffs_sem);
-
- buff = buff_pool[buff_index];
- buff_index = ((buff_index + 1) % MAX_SEND_BUFFS);
-
- height = MIN(num_rows, job_params->strip_height);
- if (!job_params->cancelled) {
- nbytes = wprint_image_decode_stripe(image_info, image_row, &height,
- (unsigned char *) buff);
-
- if (blank_data > 0) {
- blank_data--;
- }
- } else if (blank_data < MAX_SEND_BUFFS) {
- nbytes = buff_size;
- memset(buff, 0xff, buff_size);
- blank_data++;
- }
-
- if (nbytes > 0) {
- msg.param.send.buffer = buff;
- msg.param.send.start_row = image_row;
- msg.param.send.num_rows = height;
-
- result = priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg,
- sizeof(msgQ_msg_t), NO_WAIT, MSG_Q_FIFO);
- if (result < 0) {
- sem_post(&priv->buffs_sem);
- }
-
- image_row += height;
- num_rows -= height;
- } else {
- sem_post(&priv->buffs_sem);
- if (nbytes < 0) {
- LOGE("_print_page(): ERROR: file appears to be corrupted");
- result = CORRUPT;
- }
- break;
- }
+ if (result < 0) {
+ sem_post(&priv->buffs_sem);
}
- if ((result == OK) && job_params->cancelled) {
- result = CANCELLED;
- }
-
- LOGI("_print_page(): sends done, result: %d", result);
-
- // free the buffer and eject the page
- msg.param.end_page.page = job_params->page_num;
- LOGI("_print_page(): processed %d out of"
- " %d rows of page # %d from %s to printer %s %s {%s}",
- image_row, wprint_image_get_height(image_info),
- job_params->page_num, pathname,
- (job_params->last_page) ? "- last page" : "- ",
- (job_params->cancelled) ? "- job cancelled"
- : ".",
- (result == OK) ? "OK" : "ERROR");
+ image_row += height;
+ num_rows -= height;
} else {
- msg.param.end_page.page = -1;
- result = ERROR;
- LOGE("_print_page(): plugin_pcl cannot allocate memory for image stripe");
+ sem_post(&priv->buffs_sem);
+ if (nbytes < 0) {
+ LOGE("_print_page(): ERROR: file appears to be corrupted");
+ result = CORRUPT;
+ }
+ break;
}
- for (i = 0; i < MAX_SEND_BUFFS; i++) {
- msg.param.end_page.buffers[i] = buff_pool[i];
- }
- msg.param.end_page.count = MAX_SEND_BUFFS;
- } else {
- msg.param.end_page.page = -1;
- msg.param.end_page.count = 0;
- result = CORRUPT;
- LOGE("_print_page(): file does not appear to be valid");
}
- // send the end page message
- wprint_image_cleanup(image_info);
- fclose(imgfile);
+ if ((result == OK) && job_params->cancelled) {
+ result = CANCELLED;
+ }
+
+ LOGI("_print_page(): sends done, result: %d", result);
+
+ // free the buffer and eject the page
+ msg.param.end_page.page = job_params->page_num;
+ LOGI("_print_page(): processed %d out of"
+ " %d rows of page # %d from %s to printer %s %s {%s}",
+ image_row, wprint_image_get_height(image_info), job_params->page_num, pathname,
+ (job_params->last_page) ? "- last page" : "- ",
+ (job_params->cancelled) ? "- job cancelled" : ".",
+ (result == OK) ? "OK" : "ERROR");
} else {
msg.param.end_page.page = -1;
- msg.param.end_page.count = 0;
- LOGE("_print_page(): could not open %s", pathname);
- result = CORRUPT;
+ result = ERROR;
+ LOGE("_print_page(): plugin_pcl cannot allocate memory for image stripe");
}
- free(image_info);
+ for (i = 0; i < MAX_SEND_BUFFS; i++) {
+ msg.param.end_page.buffers[i] = buff_pool[i];
+ }
+ msg.param.end_page.count = MAX_SEND_BUFFS;
+
+ // send the end page message
+ wprint_image_cleanup(image_info);
} else {
- LOGE("_print_page(): ERROR: filename was empty");
+ LOGE("_print_page(): _setup_image_info() is failed");
msg.param.end_page.page = -1;
msg.param.end_page.count = 0;
result = ERROR;
}
+ free(image_info);
msg.id = MSG_END_PAGE;
priv->job_info.wprint_ifc->msgQSend(priv->msgQ, (char *) &msg, sizeof(msgQ_msg_t), NO_WAIT,
@@ -499,7 +507,8 @@
/*
* Prints a blank page
*/
-static int _print_blank_page(wJob_t job_handle, wprint_job_params_t *job_params) {
+static int _print_blank_page(wJob_t job_handle, wprint_job_params_t *job_params,
+ const char *mime_type, const char *pathname) {
msgQ_msg_t msg;
plugin_data_t *priv;
@@ -508,6 +517,22 @@
priv = (plugin_data_t *) job_params->plugin_data;
if (priv == NULL) return ERROR;
+ if ((!job_params->face_down_tray && job_params->duplex != DUPLEX_MODE_NONE) ||
+ priv->job_info.pixel_width <= 0 || priv->job_info.pixel_height <= 0) {
+ // in this case, the page size for blank page has not been decided yet
+ // so we need to calculate it
+ wprint_image_info_t *image_info = malloc(sizeof(wprint_image_info_t));
+ if (image_info == NULL) return ERROR;
+
+ if (_setup_image_info(job_params, image_info, mime_type, pathname) == OK) {
+ priv->job_info.pixel_width = wprint_image_get_width(image_info);
+ priv->job_info.pixel_height = wprint_image_get_height(image_info);
+ priv->job_info.num_components = image_info->num_components;
+ wprint_image_cleanup(image_info);
+ }
+ free(image_info);
+ }
+
msg.id = MSG_END_PAGE;
msg.param.end_page.page = -1;
msg.param.end_page.count = 0;
diff --git a/src/com/android/bips/ImagePrintActivity.java b/src/com/android/bips/ImagePrintActivity.java
index 765303a..75e4d2f 100644
--- a/src/com/android/bips/ImagePrintActivity.java
+++ b/src/com/android/bips/ImagePrintActivity.java
@@ -36,6 +36,7 @@
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import android.print.PrintJob;
+import android.print.PrintJobId;
import android.print.PrintManager;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -66,6 +67,8 @@
"IQ", "SY", "YE", "VN", "MA"
};
+ public static PrintJobId sPrintJobId;
+
private CancellationSignal mCancellationSignal = new CancellationSignal();
private String mJobName;
private Bitmap mBitmap;
@@ -153,6 +156,7 @@
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.build();
mPrintJob = printManager.print(mJobName, new ImageAdapter(), printAttributes);
+ sPrintJobId = mPrintJob.getId();
}
@Override
@@ -305,4 +309,13 @@
return mBitmap;
}
}
+
+ /**
+ * Get the print job id from PrintManager created print job.
+ *
+ * @return A PrintJobId, can be null
+ */
+ public static PrintJobId getLastPrintJobId() {
+ return sPrintJobId;
+ }
}
diff --git a/src/com/android/bips/LocalPrintJob.java b/src/com/android/bips/LocalPrintJob.java
index 7841127..d9ff70d 100644
--- a/src/com/android/bips/LocalPrintJob.java
+++ b/src/com/android/bips/LocalPrintJob.java
@@ -312,13 +312,12 @@
BackendConstants.PARAM_ERROR_MESSAGES,
getStringifiedBlockedReasons());
break;
+ case BackendConstants.JOB_DONE_BAD_CERTIFICATE:
+ handleBadCertificate(jobStatus);
+ break;
default:
// Job failed
- if (jobStatus.getBlockedReasonId() == R.string.printer_bad_certificate) {
- handleBadCertificate(jobStatus);
- } else {
- finish(false, null);
- }
+ finish(false, null);
bundle.putString(
BackendConstants.PARAM_ERROR_MESSAGES,
getStringifiedBlockedReasons());
diff --git a/src/com/android/bips/ipp/StartJobTask.java b/src/com/android/bips/ipp/StartJobTask.java
index c176231..10aba16 100755
--- a/src/com/android/bips/ipp/StartJobTask.java
+++ b/src/com/android/bips/ipp/StartJobTask.java
@@ -30,6 +30,7 @@
import android.util.Log;
import android.view.Gravity;
+import com.android.bips.ImagePrintActivity;
import com.android.bips.jni.BackendConstants;
import com.android.bips.jni.LocalJobParams;
import com.android.bips.jni.LocalPrinterCapabilities;
@@ -113,6 +114,8 @@
mJobParams.media_type = getMediaType();
mJobParams.color_space = getColorSpace();
mJobParams.document_category = getDocumentCategory();
+ mJobParams.shared_photo = isSharedPhoto();
+ mJobParams.preserve_scaling = false;
mJobParams.job_margin_top = Math.max(mJobParams.job_margin_top, 0.0f);
mJobParams.job_margin_left = Math.max(mJobParams.job_margin_left, 0.0f);
@@ -274,4 +277,8 @@
return BackendConstants.PRINT_DOCUMENT_CATEGORY__DOCUMENT;
}
}
+
+ private boolean isSharedPhoto() {
+ return mJobInfo.getId().equals(ImagePrintActivity.getLastPrintJobId());
+ }
}
diff --git a/src/com/android/bips/jni/LocalJobParams.java b/src/com/android/bips/jni/LocalJobParams.java
index c2a0193..1f3af5b 100755
--- a/src/com/android/bips/jni/LocalJobParams.java
+++ b/src/com/android/bips/jni/LocalJobParams.java
@@ -65,6 +65,9 @@
public float source_width;
public float source_height;
+ public boolean shared_photo;
+ public boolean preserve_scaling;
+
@Override
public String toString() {
return "LocalJobParams{"
@@ -104,6 +107,8 @@
+ " document_scaling=" + document_scaling
+ " source_width=" + source_width
+ " source_height=" + source_height
+ + " shared_photo=" + shared_photo
+ + " preserve_scaling=" + preserve_scaling
+ "}";
}
}
diff --git a/src/com/android/bips/p2p/P2pConnectionProcedure.java b/src/com/android/bips/p2p/P2pConnectionProcedure.java
index 44a6995..5b2df94 100644
--- a/src/com/android/bips/p2p/P2pConnectionProcedure.java
+++ b/src/com/android/bips/p2p/P2pConnectionProcedure.java
@@ -156,7 +156,7 @@
listener.onConnectionOpen(mNetwork, mInfo);
}
}
- } else if (mInvited) {
+ } else if (mInvited && !network.isConnectedOrConnecting()) {
// Only signal connection closure if we reached the invitation phase
for (P2pConnectionListener listener : mListeners) {
listener.onConnectionClosed();
diff --git a/src/com/android/bips/ui/MoreOptionsActivity.java b/src/com/android/bips/ui/MoreOptionsActivity.java
index a8fad76..970d673 100644
--- a/src/com/android/bips/ui/MoreOptionsActivity.java
+++ b/src/com/android/bips/ui/MoreOptionsActivity.java
@@ -37,6 +37,8 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
* Launched by system in response to a "More Options" request while tracking a printer.
@@ -51,6 +53,7 @@
InetAddress mPrinterAddress;
public static final String EXTRA_PRINTER_ID = "EXTRA_PRINTER_ID";
+ private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -100,6 +103,12 @@
}
@Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mExecutorService.shutdownNow();
+ }
+
+ @Override
public void onServiceConnected(ComponentName name, IBinder service) {
mPrintService = BuiltInPrintService.getInstance();
mPrintService.getDiscovery().start(this);
@@ -116,17 +125,23 @@
// We discovered a printer matching the job's PrinterId, so show recommendations
mPrinter = printer;
setTitle(mPrinter.name);
- try {
- mPrinterAddress = InetAddress.getByName(mPrinter.path.getHost());
- if (getFragmentManager().getFragments().isEmpty()) {
- MoreOptionsFragment fragment = new MoreOptionsFragment();
- getFragmentManager().beginTransaction()
- .replace(android.R.id.content, fragment)
- .commit();
- }
- // No need for continued discovery after we find the printer.
- mPrintService.getDiscovery().stop(this);
- } catch (UnknownHostException ignored) { }
+ mExecutorService.execute(() -> {
+ try {
+ mPrinterAddress = InetAddress.getByName(mPrinter.path.getHost());
+ // No need for continued discovery after we find the printer.
+ mPrintService.getDiscovery().stop(this);
+ if (!mExecutorService.isShutdown() && mPrintService != null) {
+ mPrintService.getMainHandler().post(() -> {
+ if (getFragmentManager().getFragments().isEmpty()) {
+ MoreOptionsFragment fragment = new MoreOptionsFragment();
+ getFragmentManager().beginTransaction()
+ .replace(android.R.id.content, fragment)
+ .commit();
+ }
+ });
+ }
+ } catch (UnknownHostException ignored) { }
+ });
}
}
diff --git a/src/com/android/bips/util/BroadcastMonitor.java b/src/com/android/bips/util/BroadcastMonitor.java
index 37d53fd..8a68dbf 100644
--- a/src/com/android/bips/util/BroadcastMonitor.java
+++ b/src/com/android/bips/util/BroadcastMonitor.java
@@ -41,7 +41,7 @@
}
mContext = context;
mReceiver = receiver;
- mContext.registerReceiver(this, filter);
+ mContext.registerReceiver(this, filter, Context.RECEIVER_EXPORTED/*UNAUDITED*/);
}
/** Stop monitoring for broadcast intents */