1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  * Copyright (C) 2014-2016 Mopria Alliance, Inc.
4  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <jni.h>
20 #include "lib_wprint.h"
21 #include "wprint_debug.h"
22 #include <errno.h>
23 #include <bits/strcasecmp.h>
24 #include <string.h>
25 #include "../plugins/wprint_mupdf.h"
26 
27 #define TAG "wprintJNI"
28 
29 #define MAX_NUM_PAGES 2000
30 
31 static jclass _LocalJobParamsClass;
32 static jfieldID _LocalJobParamsField__borderless;
33 static jfieldID _LocalJobParamsField__duplex;
34 static jfieldID _LocalJobParamsField__media_size;
35 static jfieldID _LocalJobParamsField__media_type;
36 static jfieldID _LocalJobParamsField__media_tray;
37 static jfieldID _LocalJobParamsField__color_space;
38 static jfieldID _LocalJobParamsField__render_flags;
39 static jfieldID _LocalJobParamsField__num_copies;
40 static jfieldID _LocalJobParamsField__page_range;
41 static jfieldID _LocalJobParamsField__print_resolution;
42 static jfieldID _LocalJobParamsField__printable_width;
43 static jfieldID _LocalJobParamsField__printable_height;
44 static jfieldID _LocalJobParamsField__page_width;
45 static jfieldID _LocalJobParamsField__page_height;
46 static jfieldID _LocalJobParamsField__page_margin_top;
47 static jfieldID _LocalJobParamsField__page_margin_left;
48 static jfieldID _LocalJobParamsField__page_margin_right;
49 static jfieldID _LocalJobParamsField__page_margin_bottom;
50 static jfieldID _LocalJobParamsField__job_margin_top;
51 static jfieldID _LocalJobParamsField__job_margin_left;
52 static jfieldID _LocalJobParamsField__job_margin_right;
53 static jfieldID _LocalJobParamsField__job_margin_bottom;
54 static jfieldID _LocalJobParamsField__fit_to_page;
55 static jfieldID _LocalJobParamsField__fill_page;
56 static jfieldID _LocalJobParamsField__auto_rotate;
57 static jfieldID _LocalJobParamsField__portrait_mode;
58 static jfieldID _LocalJobParamsField__landscape_mode;
59 static jfieldID _LocalJobParamsField__nativeData;
60 static jfieldID _LocalJobParamsField__document_category;
61 static jfieldID _LocalJobParamsField__alignment;
62 static jfieldID _LocalJobParamsField__document_scaling;
63 static jfieldID _LocalJobParamsField__job_name;
64 static jfieldID _LocalJobParamsField__job_originating_user_name;
65 static jfieldID _LocalJobParamsField__pdf_render_resolution;
66 static jfieldID _LocalJobParamsField__source_width;
67 static jfieldID _LocalJobParamsField__source_height;
68 static jfieldID _LocalJobParamsField__shared_photo;
69 static jfieldID _LocalJobParamsField__preserve_scaling;
70 
71 static jclass _LocalPrinterCapabilitiesClass;
72 static jfieldID _LocalPrinterCapabilitiesField__name;
73 static jfieldID _LocalPrinterCapabilitiesField__path;
74 static jfieldID _LocalPrinterCapabilitiesField__uuid;
75 static jfieldID _LocalPrinterCapabilitiesField__location;
76 static jfieldID _LocalPrinterCapabilitiesField__duplex;
77 static jfieldID _LocalPrinterCapabilitiesField__borderless;
78 static jfieldID _LocalPrinterCapabilitiesField__color;
79 static jfieldID _LocalPrinterCapabilitiesField__isSupported;
80 static jfieldID _LocalPrinterCapabilitiesField__mediaDefault;
81 static jfieldID _LocalPrinterCapabilitiesField__supportedMediaTypes;
82 static jfieldID _LocalPrinterCapabilitiesField__supportedMediaSizes;
83 static jfieldID _LocalPrinterCapabilitiesField__nativeData;
84 static jfieldID _LocalPrinterCapabilitiesField__certificate;
85 
86 static jclass _JobCallbackClass;
87 static jobject _callbackReceiver;
88 static jmethodID _JobCallbackMethod__jobCallback;
89 
90 static jclass _JobCallbackParamsClass;
91 static jmethodID _JobCallbackParamsMethod__init;
92 static jfieldID _JobCallbackParamsField__jobId;
93 static jfieldID _JobCallbackParamsField__jobState;
94 static jfieldID _JobCallbackParamsField__jobDoneResult;
95 static jfieldID _JobCallbackParamsField__blockedReasons;
96 static jfieldID _JobCallbackParamsField__certificate;
97 
98 static jclass _PrintServiceStringsClass;
99 static jfieldID _PrintServiceStringsField__JOB_STATE_QUEUED;
100 static jfieldID _PrintServiceStringsField__JOB_STATE_RUNNING;
101 static jfieldID _PrintServiceStringsField__JOB_STATE_BLOCKED;
102 static jfieldID _PrintServiceStringsField__JOB_STATE_DONE;
103 static jfieldID _PrintServiceStringsField__JOB_STATE_OTHER;
104 static jfieldID _PrintServiceStringsField__JOB_DONE_OK;
105 static jfieldID _PrintServiceStringsField__JOB_DONE_ERROR;
106 static jfieldID _PrintServiceStringsField__JOB_DONE_CANCELLED;
107 static jfieldID _PrintServiceStringsField__JOB_DONE_CORRUPT;
108 static jfieldID _PrintServiceStringsField__JOB_DONE_OTHER;
109 static jfieldID _PrintServiceStringsField__JOB_DONE_AUTHENTICATION_CANCELED;
110 static jfieldID _PrintServiceStringsField__JOB_DONE_ACCOUNT_INFO_NEEDED;
111 static jfieldID _PrintServiceStringsField__JOB_DONE_ACCOUNT_CLOSED;
112 static jfieldID _PrintServiceStringsField__JOB_DONE_ACCOUNT_LIMIT_REACHED;
113 static jfieldID _PrintServiceStringsField__JOB_DONE_AUTHORIZATION_FAILED;
114 static jfieldID _PrintServiceStringsField__JOB_DONE_SIDES_UNSUPPORTED;
115 static jfieldID _PrintServiceStringsField__JOB_DONE_BAD_CERTIFICATE;
116 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OFFLINE;
117 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__BUSY;
118 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__CANCELLED;
119 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_PAPER;
120 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_INK;
121 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_TONER;
122 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__JAMMED;
123 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__DOOR_OPEN;
124 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SERVICE_REQUEST;
125 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_INK;
126 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_TONER;
127 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__REALLY_LOW_ON_INK;
128 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__BAD_CERTIFICATE;
129 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__UNKNOWN;
130 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__PAUSED;
131 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__STOPPED;
132 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__INPUT_CANNOT_FEED_SIZE_SELECTED;
133 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__INTERLOCK_ERROR;
134 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUTPUT_MAILBOX_SELECT_FAILURE;
135 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUTPUT_TRAY_MISSING;
136 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__BANDER_ERROR;
137 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__BINDER_ERROR;
138 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__POWER_ERROR;
139 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__CLEANER_ERROR;
140 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__DIE_CUTTER_ERROR;
141 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__FOLDER_ERROR;
142 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__IMPRINTER_ERROR;
143 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__INPUT_TRAY_ERROR;
144 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__INSERTER_ERROR;
145 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__INTERPRETER_ERROR;
146 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__MAKE_ENVELOPE_ERROR;
147 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__MARKER_ERROR;
148 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__MEDIA_ERROR;
149 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__PERFORATER_ERROR;
150 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__PUNCHER_ERROR;
151 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SEPARATION_CUTTER_ERROR;
152 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SHEET_ROTATOR_ERROR;
153 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SLITTER_ERROR;
154 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__STACKER_ERROR;
155 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__STAPLER_ERROR;
156 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__STITCHER_ERROR;
157 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SUBUNIT_ERROR;
158 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__TRIMMER_ERROR;
159 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__WRAPPER_ERROR;
160 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__CLIENT_ERROR;
161 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SERVER_ERROR;
162 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__ALERT_REMOVAL_OF_BINARY_CHANGE_ENTRY;
163 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__CONFIGURATION_CHANGED;
164 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__CONNECTING_TO_DEVICE;
165 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__DEACTIVATED;
166 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__DEVELOPER_ERROR;
167 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__HOLD_NEW_JOBS;
168 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OPC_LIFE_OVER;
169 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SPOOL_AREA_FULL;
170 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__TIMED_OUT;
171 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SHUTDOWN;
172 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__PRINTER_NMS_RESET;
173 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__PRINTER_MANUAL_RESET;
174 
175 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER;
176 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL;
177 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER_VERTICAL;
178 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL_ON_ORIENTATION;
179 
180 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__ABORTED_BY_SYSTEM;
181 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__UNSUPPORTED_COMPRESSION;
182 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__COMPRESSION_ERROR;
183 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__UNSUPPORTED_DOCUMENT_FORMAT;
184 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_FORMAT_ERROR;
185 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__SERVICE_OFFLINE;
186 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_PASSWORD_ERROR;
187 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_PERMISSION_ERROR;
188 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_SECURITY_ERROR;
189 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_UNPRINTABLE_ERROR;
190 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_ACCESS_ERROR;
191 static jfieldID _PrintServiceStringField__JOB_FAIL_REASON__SUBMISSION_INTERRUPTED;
192 
193 // Global so it can be used in PDF render code
194 JavaVM *_JVM = NULL;
195 
196 static jstring _fakeDir;
197 
198 int g_API_version = 0;
199 
200 /*
201  * Convert char * to a java object
202  */
203 static void stringToJava(JNIEnv *env, jobject obj, jfieldID id, const char *str);
204 
205 /*
206  * Retuns if the mime type is MIME_TYPE_PDF
207  */
_is_pdf_doc(const char * mime_type,const char * pathname)208 static bool _is_pdf_doc(const char *mime_type, const char *pathname) {
209     if (mime_type == NULL || pathname == NULL) {
210         return false;
211     }
212 
213     if (strcmp(mime_type, MIME_TYPE_PDF) == 0) {
214         return true;
215     }
216 
217     return false;
218 }
219 
220 /*
221  * Returns if the string is numeric
222  */
_isNumeric(const char * s)223 static int _isNumeric(const char *s) {
224     if (s == NULL || *s == '\0' || isspace(*s)) {
225         return 0;
226     }
227     char *p;
228     strtod(s, &p);
229     return *p == '\0';
230 }
231 
232 /*
233  * Outputs the number of pages in a pdf to page_count. Returns False if an error ocurred
234  */
_get_pdf_page_count(const char * mime_type,int * page_count,const char * pathname)235 static bool _get_pdf_page_count(const char *mime_type, int *page_count, const char *pathname) {
236     *page_count = 0;
237 
238     if (!_is_pdf_doc(mime_type, pathname)) {
239         return false;
240     }
241 
242     pdf_render_ifc_t *pdf_render_ifc = create_pdf_render_ifc();
243     *page_count = pdf_render_ifc->openDocument(pdf_render_ifc, pathname);
244     pdf_render_ifc->destroy(pdf_render_ifc);
245 
246     LOGI("pdf page count for %s: %d", pathname, *page_count);
247     if (*page_count < 0) {
248         LOGE("page count error");
249         *page_count = 0;
250     }
251     return true;
252 }
253 
254 /*
255  * Reorders pdf pages before sending to the printer. In general the last page is printed first.
256  * Removes pages from pages_ary if they are not in the specified range.
257  */
_order_pdf_pages(int num_pages,int * pages_ary,int * num_index,char * page_range_split)258 static bool _order_pdf_pages(int num_pages, int *pages_ary, int *num_index,
259         char *page_range_split) {
260     bool succeeded = false;
261     char num_begin_ary[5] = "";
262     char num_end_ary[5] = "";
263     int num_counter = 0;
264     bool dash_encountered = false;
265     int range_count = 0;
266 
267     // initialize to 0
268     memset(num_begin_ary, 0, 5);
269     memset(num_end_ary, 0, 5);
270 
271     for (range_count = 0; range_count < (int) strlen(page_range_split); range_count++) {
272         // skip spaces
273         if (!isspace(page_range_split[range_count])) {
274             // store first number found in range in num_begin_ary
275             // and second number (after the dash '-') in num_end_ary
276             // skip the dash ('-') character
277             if (page_range_split[range_count] == '-') {
278                 dash_encountered = true;
279                 num_counter = 0;
280                 continue;
281             }
282 
283             if (!dash_encountered) {
284                 num_begin_ary[num_counter++] = page_range_split[range_count];
285             } else {
286                 num_end_ary[num_counter++] = page_range_split[range_count];
287             }
288         }
289     }
290 
291     // fill in first cell of end num with 0 so array has a valid number
292     if (!dash_encountered) {
293         num_end_ary[0] = '0';
294     }
295 
296     // make sure numeric values are stored in num_begin_ary and num_end_ary
297     if (_isNumeric(num_begin_ary) && _isNumeric(num_end_ary)) {
298         // convert to integers
299         int num_begin = atoi(num_begin_ary);
300         int num_end = atoi(num_end_ary);
301 
302         // if ending number was 0, there was no range, only a single page number
303         // so, set it to the value of the beginning number
304         if (num_end == 0) {
305             num_end = num_begin;
306         }
307 
308         // make sure beginning and ending numbers are at least 1
309         if (num_begin > 0 && num_end > 0) {
310             // make sure the beginning and ending numbers are not greater than the page count
311             if (num_begin <= num_pages && num_end <= num_pages) {
312                 if (num_end >= num_begin) {
313                     // make sure the upper bound does not exceed the number of pages
314                     if (num_end > num_pages) {
315                         num_end = num_pages;
316                     }
317                     // store range in pages_ary in ascending order
318                     int count = 0;
319                     for (count = *num_index; count <= (*num_index + num_end - num_begin); count++) {
320                         *(pages_ary + count) = num_begin++;
321                         *num_index += 1;
322                     }
323                 } else {
324                     // reverse order
325                     // make sure the upper bound does not exceed the number of pages
326                     if (num_begin > num_pages) {
327                         num_begin = num_pages;
328                     }
329                     // store range in pages_ary in descending order
330                     int count = 0;
331                     for (count = *num_index; count <= *num_index + num_begin - num_end; count++) {
332                         *(pages_ary + count) = num_begin--;
333                         *num_index += 1;
334                     }
335                 }
336                 succeeded = true;
337             } else {
338                 LOGE("_order_pdf_pages(), ERROR: first and/or last numbers are not greater than "
339                         "%d: first num=%d, second num=%d", num_pages, num_begin, num_end);
340             }
341         } else {
342             LOGE("_order_pdf_pages(), ERROR: first and/or last numbers are not greater than 0: "
343                     "first num=%d, second num=%d", num_begin, num_end);
344         }
345     } else {
346         LOGE("_order_pdf_pages(), ERROR: first and/or last numbers are not numeric: first num=%s, "
347                 "second num=%s", num_begin_ary, num_end_ary);
348     }
349     return succeeded;
350 }
351 
352 /*
353  * Outputs page range of a pdf to page_range_str
354  */
_get_pdf_page_range(JNIEnv * env,jobject javaJobParams,int * pages_ary,int num_pages,int * num_index,char * page_range_str)355 static void _get_pdf_page_range(JNIEnv *env, jobject javaJobParams, int *pages_ary, int num_pages,
356         int *num_index, char *page_range_str) {
357     char *page_range = NULL;
358     jstring pageRangeObject = (jstring) (*env)->GetObjectField(env, javaJobParams,
359             _LocalJobParamsField__page_range);
360     if (pageRangeObject) {
361         int page_range_size = (*env)->GetStringLength(env, pageRangeObject);
362         const jbyte *pageRange = (jbyte *) (*env)->GetStringUTFChars(env, pageRangeObject, 0);
363         if (strcmp((char *) pageRange, "") != 0) {
364             page_range = (char *) malloc(page_range_size + 1);
365             memset(page_range, 0, page_range_size + 1);
366             strncpy(page_range, (char *) pageRange, page_range_size);
367 
368             // no empty strings
369             if (strcmp(page_range, "") == 0) {
370                 free(page_range);
371                 page_range = NULL;
372             }
373 
374             (*env)->ReleaseStringUTFChars(env, pageRangeObject, (const char *) pageRange);
375             LOGD("_get_pdf_page_range(), page_range from JNI environment=%s", page_range);
376         }
377     }
378 
379     if (!page_range) {
380         page_range = (char *) malloc(MAX_NUM_PAGES + 1);
381         memset(page_range, 0, MAX_NUM_PAGES + 1);
382 
383         snprintf(page_range_str, MAX_NUM_PAGES, "1-%d", num_pages);
384         snprintf(page_range, MAX_NUM_PAGES, "1-%d", num_pages);
385     } else {
386         strncpy(page_range_str, page_range, MAX_NUM_PAGES);
387     }
388 
389     LOGD("_get_pdf_page_range(), range: %s, pages in document: %d", page_range_str, num_pages);
390 
391     // get the first token in page_range_str
392     memset(pages_ary, 0, MAX_NUM_PAGES);
393     char *page_range_split = strtok(page_range, ",");
394     while (page_range_split != NULL) {
395         if (!_order_pdf_pages(num_pages, pages_ary, num_index, page_range_split)) {
396             snprintf(page_range_str, MAX_NUM_PAGES, "1-%d", num_pages);
397             LOGD("_get_pdf_page_range(), setting page_range to: %s", page_range_str);
398             _order_pdf_pages(num_pages, pages_ary, num_index, page_range_str);
399             break;
400         }
401 
402         // get next range token
403         page_range_split = strtok(NULL, ",");
404     }
405 
406     if (page_range) {
407         free(page_range);
408     }
409 }
410 
411 /*
412  * Sends a pdf to a printer
413  */
_print_pdf_pages(wJob_t job_handle,printer_capabilities_t * printer_cap,duplex_t duplex,char * pathname,int num_index,int * pages_ary)414 static jint _print_pdf_pages(wJob_t job_handle, printer_capabilities_t *printer_cap,
415         duplex_t duplex, char *pathname, int num_index, int *pages_ary) {
416     int num_pages = num_index;
417 
418     // now, print the pages
419     int page_index;
420     jint result = ERROR;
421 
422     // print forward direction if printer prints pages face down; otherwise print backward
423     // NOTE: last page is sent from calling function
424     if (printer_cap->faceDownTray) {
425         LOGD("_print_pdf_pages(), pages print face down, printing in normal order");
426         page_index = 0;
427         while (page_index < num_pages) {
428             LOGD("_print_pdf_pages(), PRINTING PDF: %d", *(pages_ary + page_index));
429             result = wprintPage(job_handle, *(pages_ary + page_index++), pathname, false, true,
430                     0, 0, 0, 0);
431 
432             if (result != OK) {
433                 break;
434             }
435         }
436     } else {
437         LOGI("   _print_pdf_pages(), pages print face up, printing in reverse");
438         page_index = num_pages - 1;
439         while (page_index >= 0) {
440             LOGD("_print_pdf_pages(), PRINTING PDF: %s, page: %d", pathname,
441                     *(pages_ary + page_index));
442             result = wprintPage(job_handle, *(pages_ary + page_index--), pathname, false, true,
443                     0, 0, 0, 0);
444             if (result != OK) {
445                 break;
446             }
447         }
448     }
449 
450     LOGI("   _print_pdf_pages(), printing result: %s", result == OK ? "OK" : "ERROR");
451     return result;
452 }
453 
454 /*
455  * Initialize JNI. Maps java values to jni values.
456  */
_initJNI(JNIEnv * env,jobject callbackReceiver,jstring fakeDir)457 static void _initJNI(JNIEnv *env, jobject callbackReceiver, jstring fakeDir) {
458     _fakeDir = (jstring) (*env)->NewGlobalRef(env, fakeDir);
459 
460     // fill out static accessors for wPrintJobParameters
461     _LocalJobParamsClass = (jclass) (*env)->NewGlobalRef(
462             env, (*env)->FindClass(env, "com/android/bips/jni/LocalJobParams"));
463     _LocalJobParamsField__borderless = (*env)->GetFieldID(env, _LocalJobParamsClass, "borderless",
464             "I");
465     _LocalJobParamsField__duplex = (*env)->GetFieldID(env, _LocalJobParamsClass, "duplex", "I");
466     _LocalJobParamsField__media_size = (*env)->GetFieldID(env, _LocalJobParamsClass, "media_size",
467             "I");
468     _LocalJobParamsField__media_type = (*env)->GetFieldID(env, _LocalJobParamsClass, "media_type",
469             "I");
470     _LocalJobParamsField__media_tray = (*env)->GetFieldID(env, _LocalJobParamsClass, "media_tray",
471             "I");
472     _LocalJobParamsField__color_space = (*env)->GetFieldID(env, _LocalJobParamsClass, "color_space",
473             "I");
474     _LocalJobParamsField__render_flags = (*env)->GetFieldID(env, _LocalJobParamsClass,
475             "render_flags", "I");
476     _LocalJobParamsField__num_copies = (*env)->GetFieldID(env, _LocalJobParamsClass, "num_copies",
477             "I");
478     _LocalJobParamsField__page_range = (*env)->GetFieldID(env, _LocalJobParamsClass, "page_range",
479             "Ljava/lang/String;");
480     _LocalJobParamsField__print_resolution = (*env)->GetFieldID(env, _LocalJobParamsClass,
481             "print_resolution", "I");
482     _LocalJobParamsField__printable_width = (*env)->GetFieldID(env, _LocalJobParamsClass,
483             "printable_width", "I");
484     _LocalJobParamsField__printable_height = (*env)->GetFieldID(env, _LocalJobParamsClass,
485             "printable_height", "I");
486     _LocalJobParamsField__page_width = (*env)->GetFieldID(env, _LocalJobParamsClass, "page_width",
487             "F");
488     _LocalJobParamsField__page_height = (*env)->GetFieldID(env, _LocalJobParamsClass, "page_height",
489             "F");
490     _LocalJobParamsField__page_margin_top = (*env)->GetFieldID(env, _LocalJobParamsClass,
491             "page_margin_top", "F");
492     _LocalJobParamsField__page_margin_left = (*env)->GetFieldID(env, _LocalJobParamsClass,
493             "page_margin_left", "F");
494     _LocalJobParamsField__page_margin_right = (*env)->GetFieldID(env, _LocalJobParamsClass,
495             "page_margin_right", "F");
496     _LocalJobParamsField__page_margin_bottom = (*env)->GetFieldID(env, _LocalJobParamsClass,
497             "page_margin_bottom", "F");
498     _LocalJobParamsField__nativeData = (*env)->GetFieldID(env, _LocalJobParamsClass, "nativeData",
499             "[B");
500     _LocalJobParamsField__fit_to_page = (*env)->GetFieldID(env, _LocalJobParamsClass, "fit_to_page",
501             "Z");
502     _LocalJobParamsField__fill_page = (*env)->GetFieldID(env, _LocalJobParamsClass, "fill_page",
503             "Z");
504     _LocalJobParamsField__shared_photo = (*env)->GetFieldID(env, _LocalJobParamsClass,
505             "shared_photo", "Z");
506     _LocalJobParamsField__preserve_scaling = (*env)->GetFieldID(env, _LocalJobParamsClass,
507             "preserve_scaling", "Z");
508     _LocalJobParamsField__auto_rotate = (*env)->GetFieldID(env, _LocalJobParamsClass, "auto_rotate",
509             "Z");
510     _LocalJobParamsField__portrait_mode = (*env)->GetFieldID(env, _LocalJobParamsClass,
511             "portrait_mode", "Z");
512     _LocalJobParamsField__landscape_mode = (*env)->GetFieldID(env, _LocalJobParamsClass,
513             "landscape_mode", "Z");
514     _LocalJobParamsField__document_category = (*env)->GetFieldID(env, _LocalJobParamsClass,
515             "document_category",
516             "Ljava/lang/String;");
517     _LocalJobParamsField__alignment = (*env)->GetFieldID(env, _LocalJobParamsClass, "alignment",
518             "I");
519     _LocalJobParamsField__job_margin_top = (*env)->GetFieldID(env, _LocalJobParamsClass,
520             "job_margin_top", "F");
521     _LocalJobParamsField__job_margin_left = (*env)->GetFieldID(env, _LocalJobParamsClass,
522             "job_margin_left", "F");
523     _LocalJobParamsField__job_margin_right = (*env)->GetFieldID(env, _LocalJobParamsClass,
524             "job_margin_right", "F");
525     _LocalJobParamsField__job_margin_bottom = (*env)->GetFieldID(env, _LocalJobParamsClass,
526             "job_margin_bottom", "F");
527     _LocalJobParamsField__document_scaling = (*env)->GetFieldID(env, _LocalJobParamsClass,
528             "document_scaling", "Z");
529     _LocalJobParamsField__job_name = (*env)->GetFieldID(env, _LocalJobParamsClass, "job_name",
530             "Ljava/lang/String;");
531     _LocalJobParamsField__job_originating_user_name = (*env)->GetFieldID(
532             env, _LocalJobParamsClass, "job_originating_user_name", "Ljava/lang/String;");
533     _LocalJobParamsField__pdf_render_resolution = (*env)->GetFieldID(env, _LocalJobParamsClass,
534             "pdf_render_resolution", "I");
535     _LocalJobParamsField__source_width = (*env)->GetFieldID(env, _LocalJobParamsClass,
536                                                             "source_width", "F");
537     _LocalJobParamsField__source_height = (*env)->GetFieldID(env, _LocalJobParamsClass,
538                                                              "source_height", "F");
539 
540     // fill out static accessors for LocalPrinterCapabilities
541     _LocalPrinterCapabilitiesClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(
542             env, "com/android/bips/jni/LocalPrinterCapabilities"));
543     _LocalPrinterCapabilitiesField__path = (*env)->GetFieldID(
544             env, _LocalPrinterCapabilitiesClass, "path", "Ljava/lang/String;");
545     _LocalPrinterCapabilitiesField__name = (*env)->GetFieldID(
546             env, _LocalPrinterCapabilitiesClass, "name", "Ljava/lang/String;");
547     _LocalPrinterCapabilitiesField__uuid = (*env)->GetFieldID(
548             env, _LocalPrinterCapabilitiesClass, "uuid", "Ljava/lang/String;");
549     _LocalPrinterCapabilitiesField__location = (*env)->GetFieldID(
550             env, _LocalPrinterCapabilitiesClass, "location", "Ljava/lang/String;");
551     _LocalPrinterCapabilitiesField__duplex = (*env)->GetFieldID(
552             env, _LocalPrinterCapabilitiesClass, "duplex", "Z");
553     _LocalPrinterCapabilitiesField__borderless = (*env)->GetFieldID(
554             env, _LocalPrinterCapabilitiesClass, "borderless", "Z");
555     _LocalPrinterCapabilitiesField__color = (*env)->GetFieldID(
556             env, _LocalPrinterCapabilitiesClass, "color", "Z");
557     _LocalPrinterCapabilitiesField__isSupported = (*env)->GetFieldID(
558             env, _LocalPrinterCapabilitiesClass, "isSupported", "Z");
559     _LocalPrinterCapabilitiesField__mediaDefault = (*env)->GetFieldID(
560             env, _LocalPrinterCapabilitiesClass, "mediaDefault", "Ljava/lang/String;");
561     _LocalPrinterCapabilitiesField__supportedMediaTypes = (*env)->GetFieldID(
562             env, _LocalPrinterCapabilitiesClass, "supportedMediaTypes", "[I");
563     _LocalPrinterCapabilitiesField__supportedMediaSizes = (*env)->GetFieldID(
564             env, _LocalPrinterCapabilitiesClass, "supportedMediaSizes", "[I");
565     _LocalPrinterCapabilitiesField__nativeData = (*env)->GetFieldID(
566             env, _LocalPrinterCapabilitiesClass, "nativeData", "[B");
567     _LocalPrinterCapabilitiesField__certificate = (*env)->GetFieldID(
568             env, _LocalPrinterCapabilitiesClass, "certificate", "[B");
569 
570     _JobCallbackParamsClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(
571             env, "com/android/bips/jni/JobCallbackParams"));
572     _JobCallbackParamsMethod__init = (*env)->GetMethodID(env, _JobCallbackParamsClass,
573             "<init>", "()V");
574     _JobCallbackParamsField__jobId = (*env)->GetFieldID(env, _JobCallbackParamsClass, "jobId",
575             "I");
576     _JobCallbackParamsField__jobState = (*env)->GetFieldID(
577             env, _JobCallbackParamsClass, "jobState", "Ljava/lang/String;");
578     _JobCallbackParamsField__jobDoneResult = (*env)->GetFieldID(
579             env, _JobCallbackParamsClass, "jobDoneResult", "Ljava/lang/String;");
580     _JobCallbackParamsField__blockedReasons = (*env)->GetFieldID(
581             env, _JobCallbackParamsClass, "blockedReasons", "[Ljava/lang/String;");
582     _JobCallbackParamsField__certificate = (*env)->GetFieldID(
583             env, _JobCallbackParamsClass, "certificate", "[B");
584 
585     if (callbackReceiver) {
586         _callbackReceiver = (jobject) (*env)->NewGlobalRef(env, callbackReceiver);
587     }
588     if (_callbackReceiver) {
589         _JobCallbackClass = (jclass) (*env)->NewGlobalRef(env, (*env)->GetObjectClass(
590                 env, _callbackReceiver));
591         _JobCallbackMethod__jobCallback = (*env)->GetMethodID(
592                 env, _JobCallbackClass, "jobCallback",
593                 "(ILcom/android/bips/jni/JobCallbackParams;)V");
594     } else {
595         _callbackReceiver = 0;
596     }
597 
598     _PrintServiceStringsClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(
599             env, "com/android/bips/jni/BackendConstants"));
600     _PrintServiceStringsField__JOB_STATE_QUEUED = (*env)->GetStaticFieldID(
601             env, _PrintServiceStringsClass, "JOB_STATE_QUEUED", "Ljava/lang/String;");
602     _PrintServiceStringsField__JOB_STATE_RUNNING = (*env)->GetStaticFieldID(
603             env, _PrintServiceStringsClass, "JOB_STATE_RUNNING", "Ljava/lang/String;");
604     _PrintServiceStringsField__JOB_STATE_BLOCKED = (*env)->GetStaticFieldID(
605             env, _PrintServiceStringsClass, "JOB_STATE_BLOCKED", "Ljava/lang/String;");
606     _PrintServiceStringsField__JOB_STATE_DONE = (*env)->GetStaticFieldID(
607             env, _PrintServiceStringsClass, "JOB_STATE_DONE", "Ljava/lang/String;");
608     _PrintServiceStringsField__JOB_STATE_OTHER = (*env)->GetStaticFieldID(
609             env, _PrintServiceStringsClass, "JOB_STATE_OTHER", "Ljava/lang/String;");
610     _PrintServiceStringsField__JOB_DONE_OK = (*env)->GetStaticFieldID(
611             env, _PrintServiceStringsClass, "JOB_DONE_OK", "Ljava/lang/String;");
612     _PrintServiceStringsField__JOB_DONE_ERROR = (*env)->GetStaticFieldID(
613             env, _PrintServiceStringsClass, "JOB_DONE_ERROR", "Ljava/lang/String;");
614     _PrintServiceStringsField__JOB_DONE_CANCELLED = (*env)->GetStaticFieldID(
615             env, _PrintServiceStringsClass, "JOB_DONE_CANCELLED", "Ljava/lang/String;");
616     _PrintServiceStringsField__JOB_DONE_CORRUPT = (*env)->GetStaticFieldID(
617             env, _PrintServiceStringsClass, "JOB_DONE_CORRUPT", "Ljava/lang/String;");
618     _PrintServiceStringsField__JOB_DONE_OTHER = (*env)->GetStaticFieldID(
619             env, _PrintServiceStringsClass, "JOB_DONE_OTHER", "Ljava/lang/String;");
620     _PrintServiceStringsField__JOB_DONE_AUTHENTICATION_CANCELED = (*env)->GetStaticFieldID(env,
621             _PrintServiceStringsClass, "JOB_DONE_AUTHENTICATION_CANCELED", "Ljava/lang/String;");
622     _PrintServiceStringsField__JOB_DONE_ACCOUNT_INFO_NEEDED = (*env)->GetStaticFieldID(env,
623             _PrintServiceStringsClass, "JOB_DONE_ACCOUNT_INFO_NEEDED", "Ljava/lang/String;");
624     _PrintServiceStringsField__JOB_DONE_ACCOUNT_CLOSED = (*env)->GetStaticFieldID(env,
625             _PrintServiceStringsClass, "JOB_DONE_ACCOUNT_CLOSED", "Ljava/lang/String;");
626     _PrintServiceStringsField__JOB_DONE_ACCOUNT_LIMIT_REACHED = (*env)->GetStaticFieldID(env,
627             _PrintServiceStringsClass, "JOB_DONE_ACCOUNT_LIMIT_REACHED", "Ljava/lang/String;");
628     _PrintServiceStringsField__JOB_DONE_AUTHORIZATION_FAILED = (*env)->GetStaticFieldID(env,
629             _PrintServiceStringsClass, "JOB_DONE_AUTHORIZATION_FAILED", "Ljava/lang/String;");
630     _PrintServiceStringsField__JOB_DONE_SIDES_UNSUPPORTED = (*env)->GetStaticFieldID(env,
631             _PrintServiceStringsClass, "JOB_DONE_SIDES_UNSUPPORTED", "Ljava/lang/String;");
632     _PrintServiceStringsField__JOB_DONE_BAD_CERTIFICATE = (*env)->GetStaticFieldID(env,
633             _PrintServiceStringsClass, "JOB_DONE_BAD_CERTIFICATE", "Ljava/lang/String;");
634     _PrintServiceStringsField__BLOCKED_REASON__OFFLINE = (*env)->GetStaticFieldID(
635             env, _PrintServiceStringsClass, "BLOCKED_REASON__OFFLINE", "Ljava/lang/String;");
636     _PrintServiceStringsField__BLOCKED_REASON__BUSY = (*env)->GetStaticFieldID(
637             env, _PrintServiceStringsClass, "BLOCKED_REASON__BUSY", "Ljava/lang/String;");
638     _PrintServiceStringsField__BLOCKED_REASON__CANCELLED = (*env)->GetStaticFieldID(
639             env, _PrintServiceStringsClass, "BLOCKED_REASON__CANCELLED", "Ljava/lang/String;");
640     _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_PAPER = (*env)->GetStaticFieldID(
641             env, _PrintServiceStringsClass, "BLOCKED_REASON__OUT_OF_PAPER", "Ljava/lang/String;");
642     _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_INK = (*env)->GetStaticFieldID(
643             env, _PrintServiceStringsClass, "BLOCKED_REASON__OUT_OF_INK", "Ljava/lang/String;");
644     _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_TONER = (*env)->GetStaticFieldID(
645             env, _PrintServiceStringsClass, "BLOCKED_REASON__OUT_OF_TONER", "Ljava/lang/String;");
646     _PrintServiceStringsField__BLOCKED_REASON__JAMMED = (*env)->GetStaticFieldID(
647             env, _PrintServiceStringsClass, "BLOCKED_REASON__JAMMED", "Ljava/lang/String;");
648     _PrintServiceStringsField__BLOCKED_REASON__DOOR_OPEN = (*env)->GetStaticFieldID(
649             env, _PrintServiceStringsClass, "BLOCKED_REASON__DOOR_OPEN", "Ljava/lang/String;");
650     _PrintServiceStringsField__BLOCKED_REASON__SERVICE_REQUEST = (*env)->GetStaticFieldID(
651             env, _PrintServiceStringsClass, "BLOCKED_REASON__SERVICE_REQUEST",
652             "Ljava/lang/String;");
653     _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_INK = (*env)->GetStaticFieldID(
654             env, _PrintServiceStringsClass, "BLOCKED_REASON__LOW_ON_INK", "Ljava/lang/String;");
655     _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_TONER = (*env)->GetStaticFieldID(
656             env, _PrintServiceStringsClass, "BLOCKED_REASON__LOW_ON_TONER", "Ljava/lang/String;");
657     _PrintServiceStringsField__BLOCKED_REASON__REALLY_LOW_ON_INK = (*env)->GetStaticFieldID(
658             env, _PrintServiceStringsClass, "BLOCKED_REASON__REALLY_LOW_ON_INK",
659             "Ljava/lang/String;");
660     _PrintServiceStringsField__BLOCKED_REASON__BAD_CERTIFICATE = (*env)->GetStaticFieldID(
661             env, _PrintServiceStringsClass, "BLOCKED_REASON__BAD_CERTIFICATE",
662             "Ljava/lang/String;");
663     _PrintServiceStringsField__BLOCKED_REASON__UNKNOWN = (*env)->GetStaticFieldID(
664             env, _PrintServiceStringsClass, "BLOCKED_REASON__UNKNOWN", "Ljava/lang/String;");
665     _PrintServiceStringsField__BLOCKED_REASON__PAUSED = (*env)->GetStaticFieldID(env,
666             _PrintServiceStringsClass, "BLOCKED_REASON__PAUSED", "Ljava/lang/String;");
667     _PrintServiceStringsField__BLOCKED_REASON__STOPPED = (*env)->GetStaticFieldID(env,
668             _PrintServiceStringsClass, "BLOCKED_REASON__STOPPED", "Ljava/lang/String;");
669     _PrintServiceStringsField__BLOCKED_REASON__INPUT_CANNOT_FEED_SIZE_SELECTED =
670             (*env)->GetStaticFieldID(env, _PrintServiceStringsClass,
671             "BLOCKED_REASON__INPUT_CANNOT_FEED_SIZE_SELECTED", "Ljava/lang/String;");
672     _PrintServiceStringsField__BLOCKED_REASON__INTERLOCK_ERROR = (*env)->GetStaticFieldID(env,
673             _PrintServiceStringsClass, "BLOCKED_REASON__INTERLOCK_ERROR", "Ljava/lang/String;");
674     _PrintServiceStringsField__BLOCKED_REASON__OUTPUT_MAILBOX_SELECT_FAILURE =
675             (*env)->GetStaticFieldID(env, _PrintServiceStringsClass,
676             "BLOCKED_REASON__OUTPUT_MAILBOX_SELECT_FAILURE", "Ljava/lang/String;");
677     _PrintServiceStringsField__BLOCKED_REASON__OUTPUT_TRAY_MISSING = (*env)->GetStaticFieldID(env,
678             _PrintServiceStringsClass, "BLOCKED_REASON__OUTPUT_TRAY_MISSING", "Ljava/lang/String;");
679     _PrintServiceStringsField__BLOCKED_REASON__BANDER_ERROR = (*env)->GetStaticFieldID(env,
680             _PrintServiceStringsClass, "BLOCKED_REASON__BANDER_ERROR", "Ljava/lang/String;");
681     _PrintServiceStringsField__BLOCKED_REASON__BINDER_ERROR = (*env)->GetStaticFieldID(env,
682             _PrintServiceStringsClass, "BLOCKED_REASON__BINDER_ERROR", "Ljava/lang/String;");
683     _PrintServiceStringsField__BLOCKED_REASON__POWER_ERROR = (*env)->GetStaticFieldID(env,
684             _PrintServiceStringsClass, "BLOCKED_REASON__POWER_ERROR", "Ljava/lang/String;");
685     _PrintServiceStringsField__BLOCKED_REASON__CLEANER_ERROR = (*env)->GetStaticFieldID(env,
686             _PrintServiceStringsClass, "BLOCKED_REASON__CLEANER_ERROR", "Ljava/lang/String;");
687     _PrintServiceStringsField__BLOCKED_REASON__DIE_CUTTER_ERROR = (*env)->GetStaticFieldID(env,
688             _PrintServiceStringsClass, "BLOCKED_REASON__DIE_CUTTER_ERROR", "Ljava/lang/String;");
689     _PrintServiceStringsField__BLOCKED_REASON__FOLDER_ERROR = (*env)->GetStaticFieldID(env,
690             _PrintServiceStringsClass, "BLOCKED_REASON__FOLDER_ERROR", "Ljava/lang/String;");
691     _PrintServiceStringsField__BLOCKED_REASON__IMPRINTER_ERROR = (*env)->GetStaticFieldID(env,
692             _PrintServiceStringsClass, "BLOCKED_REASON__IMPRINTER_ERROR", "Ljava/lang/String;");
693     _PrintServiceStringsField__BLOCKED_REASON__INPUT_TRAY_ERROR = (*env)->GetStaticFieldID(env,
694             _PrintServiceStringsClass, "BLOCKED_REASON__INPUT_TRAY_ERROR", "Ljava/lang/String;");
695     _PrintServiceStringsField__BLOCKED_REASON__INSERTER_ERROR = (*env)->GetStaticFieldID(env,
696             _PrintServiceStringsClass, "BLOCKED_REASON__INSERTER_ERROR", "Ljava/lang/String;");
697     _PrintServiceStringsField__BLOCKED_REASON__INTERPRETER_ERROR = (*env)->GetStaticFieldID(env,
698             _PrintServiceStringsClass, "BLOCKED_REASON__INTERPRETER_ERROR", "Ljava/lang/String;");
699     _PrintServiceStringsField__BLOCKED_REASON__MAKE_ENVELOPE_ERROR = (*env)->GetStaticFieldID(env,
700             _PrintServiceStringsClass, "BLOCKED_REASON__MAKE_ENVELOPE_ERROR", "Ljava/lang/String;");
701     _PrintServiceStringsField__BLOCKED_REASON__MARKER_ERROR = (*env)->GetStaticFieldID(env,
702             _PrintServiceStringsClass, "BLOCKED_REASON__MARKER_ERROR", "Ljava/lang/String;");
703     _PrintServiceStringsField__BLOCKED_REASON__MEDIA_ERROR = (*env)->GetStaticFieldID(env,
704             _PrintServiceStringsClass, "BLOCKED_REASON__MEDIA_ERROR", "Ljava/lang/String;");
705     _PrintServiceStringsField__BLOCKED_REASON__PERFORATER_ERROR = (*env)->GetStaticFieldID(env,
706             _PrintServiceStringsClass, "BLOCKED_REASON__PERFORATER_ERROR", "Ljava/lang/String;");
707     _PrintServiceStringsField__BLOCKED_REASON__PUNCHER_ERROR = (*env)->GetStaticFieldID(env,
708             _PrintServiceStringsClass, "BLOCKED_REASON__PUNCHER_ERROR", "Ljava/lang/String;");
709     _PrintServiceStringsField__BLOCKED_REASON__SEPARATION_CUTTER_ERROR = (*env)->GetStaticFieldID(
710             env, _PrintServiceStringsClass, "BLOCKED_REASON__SEPARATION_CUTTER_ERROR",
711             "Ljava/lang/String;");
712     _PrintServiceStringsField__BLOCKED_REASON__SHEET_ROTATOR_ERROR = (*env)->GetStaticFieldID(env,
713             _PrintServiceStringsClass, "BLOCKED_REASON__SHEET_ROTATOR_ERROR", "Ljava/lang/String;");
714     _PrintServiceStringsField__BLOCKED_REASON__SLITTER_ERROR = (*env)->GetStaticFieldID(env,
715             _PrintServiceStringsClass, "BLOCKED_REASON__SLITTER_ERROR", "Ljava/lang/String;");
716     _PrintServiceStringsField__BLOCKED_REASON__STACKER_ERROR = (*env)->GetStaticFieldID(env,
717             _PrintServiceStringsClass, "BLOCKED_REASON__STACKER_ERROR", "Ljava/lang/String;");
718     _PrintServiceStringsField__BLOCKED_REASON__STAPLER_ERROR = (*env)->GetStaticFieldID(env,
719             _PrintServiceStringsClass, "BLOCKED_REASON__STAPLER_ERROR", "Ljava/lang/String;");
720     _PrintServiceStringsField__BLOCKED_REASON__STITCHER_ERROR = (*env)->GetStaticFieldID(env,
721             _PrintServiceStringsClass, "BLOCKED_REASON__STITCHER_ERROR", "Ljava/lang/String;");
722     _PrintServiceStringsField__BLOCKED_REASON__SUBUNIT_ERROR = (*env)->GetStaticFieldID(env,
723             _PrintServiceStringsClass, "BLOCKED_REASON__SUBUNIT_ERROR", "Ljava/lang/String;");
724     _PrintServiceStringsField__BLOCKED_REASON__TRIMMER_ERROR = (*env)->GetStaticFieldID(env,
725             _PrintServiceStringsClass, "BLOCKED_REASON__TRIMMER_ERROR", "Ljava/lang/String;");
726     _PrintServiceStringsField__BLOCKED_REASON__WRAPPER_ERROR = (*env)->GetStaticFieldID(env,
727             _PrintServiceStringsClass, "BLOCKED_REASON__WRAPPER_ERROR", "Ljava/lang/String;");
728     _PrintServiceStringsField__BLOCKED_REASON__CLIENT_ERROR = (*env)->GetStaticFieldID(env,
729             _PrintServiceStringsClass, "BLOCKED_REASON__CLIENT_ERROR", "Ljava/lang/String;");
730     _PrintServiceStringsField__BLOCKED_REASON__SERVER_ERROR = (*env)->GetStaticFieldID(env,
731             _PrintServiceStringsClass, "BLOCKED_REASON__SERVER_ERROR", "Ljava/lang/String;");
732     _PrintServiceStringsField__BLOCKED_REASON__ALERT_REMOVAL_OF_BINARY_CHANGE_ENTRY =
733             (*env)->GetStaticFieldID(env, _PrintServiceStringsClass,
734             "BLOCKED_REASON__ALERT_REMOVAL_OF_BINARY_CHANGE_ENTRY", "Ljava/lang/String;");
735     _PrintServiceStringsField__BLOCKED_REASON__CONFIGURATION_CHANGED = (*env)->GetStaticFieldID(env,
736             _PrintServiceStringsClass, "BLOCKED_REASON__CONFIGURATION_CHANGED",
737             "Ljava/lang/String;");
738     _PrintServiceStringsField__BLOCKED_REASON__CONNECTING_TO_DEVICE = (*env)->GetStaticFieldID(env,
739             _PrintServiceStringsClass, "BLOCKED_REASON__CONNECTING_TO_DEVICE",
740             "Ljava/lang/String;");
741     _PrintServiceStringsField__BLOCKED_REASON__DEACTIVATED = (*env)->GetStaticFieldID(env,
742             _PrintServiceStringsClass, "BLOCKED_REASON__DEACTIVATED", "Ljava/lang/String;");
743     _PrintServiceStringsField__BLOCKED_REASON__DEVELOPER_ERROR = (*env)->GetStaticFieldID(env,
744             _PrintServiceStringsClass, "BLOCKED_REASON__DEVELOPER_ERROR", "Ljava/lang/String;");
745     _PrintServiceStringsField__BLOCKED_REASON__HOLD_NEW_JOBS = (*env)->GetStaticFieldID(env,
746             _PrintServiceStringsClass, "BLOCKED_REASON__HOLD_NEW_JOBS", "Ljava/lang/String;");
747     _PrintServiceStringsField__BLOCKED_REASON__OPC_LIFE_OVER = (*env)->GetStaticFieldID(env,
748             _PrintServiceStringsClass, "BLOCKED_REASON__OPC_LIFE_OVER", "Ljava/lang/String;");
749     _PrintServiceStringsField__BLOCKED_REASON__SPOOL_AREA_FULL = (*env)->GetStaticFieldID(env,
750             _PrintServiceStringsClass, "BLOCKED_REASON__SPOOL_AREA_FULL", "Ljava/lang/String;");
751     _PrintServiceStringsField__BLOCKED_REASON__SHUTDOWN = (*env)->GetStaticFieldID(env,
752             _PrintServiceStringsClass, "BLOCKED_REASON__SHUTDOWN", "Ljava/lang/String;");
753     _PrintServiceStringsField__BLOCKED_REASON__TIMED_OUT = (*env)->GetStaticFieldID(env,
754             _PrintServiceStringsClass, "BLOCKED_REASON__TIMED_OUT", "Ljava/lang/String;");
755     _PrintServiceStringsField__BLOCKED_REASON__PRINTER_MANUAL_RESET = (*env)->GetStaticFieldID(env,
756             _PrintServiceStringsClass, "BLOCKED_REASON__PRINTER_MANUAL_RESET",
757             "Ljava/lang/String;");
758     _PrintServiceStringsField__BLOCKED_REASON__PRINTER_NMS_RESET = (*env)->GetStaticFieldID(env,
759             _PrintServiceStringsClass, "BLOCKED_REASON__PRINTER_NMS_RESET", "Ljava/lang/String;");
760 
761     _PrintServiceStringsField__ALIGNMENT__CENTER = (*env)->GetStaticFieldID(
762             env, _PrintServiceStringsClass, "ALIGN_CENTER", "I");
763     _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL = (*env)->GetStaticFieldID(
764             env, _PrintServiceStringsClass, "ALIGN_CENTER_HORIZONTAL", "I");
765     _PrintServiceStringsField__ALIGNMENT__CENTER_VERTICAL = (*env)->GetStaticFieldID(
766             env, _PrintServiceStringsClass, "ALIGN_CENTER_VERTICIAL", "I");
767     _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL_ON_ORIENTATION =
768             (*env)->GetStaticFieldID(env, _PrintServiceStringsClass,
769                     "ALIGN_CENTER_HORIZONTAL_ON_ORIENTATION", "I");
770 
771     _PrintServiceStringField__JOB_FAIL_REASON__ABORTED_BY_SYSTEM = (*env)->GetStaticFieldID(env,
772             _PrintServiceStringsClass, "JOB_FAIL_REASON__ABORTED_BY_SYSTEM", "Ljava/lang/String;");
773     _PrintServiceStringField__JOB_FAIL_REASON__UNSUPPORTED_COMPRESSION = (*env)->GetStaticFieldID(
774             env, _PrintServiceStringsClass, "JOB_FAIL_REASON__UNSUPPORTED_COMPRESSION",
775             "Ljava/lang/String;");
776     _PrintServiceStringField__JOB_FAIL_REASON__COMPRESSION_ERROR = (*env)->GetStaticFieldID(env,
777             _PrintServiceStringsClass, "JOB_FAIL_REASON__COMPRESSION_ERROR", "Ljava/lang/String;");
778     _PrintServiceStringField__JOB_FAIL_REASON__UNSUPPORTED_DOCUMENT_FORMAT =
779             (*env)->GetStaticFieldID(env, _PrintServiceStringsClass,
780             "JOB_FAIL_REASON__UNSUPPORTED_DOCUMENT_FORMAT", "Ljava/lang/String;");
781     _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_FORMAT_ERROR = (*env)->GetStaticFieldID(env,
782             _PrintServiceStringsClass, "JOB_FAIL_REASON__DOCUMENT_FORMAT_ERROR",
783             "Ljava/lang/String;");
784     _PrintServiceStringField__JOB_FAIL_REASON__SERVICE_OFFLINE = (*env)->GetStaticFieldID(env,
785             _PrintServiceStringsClass, "JOB_FAIL_REASON__SERVICE_OFFLINE", "Ljava/lang/String;");
786     _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_PASSWORD_ERROR = (*env)->GetStaticFieldID(
787             env, _PrintServiceStringsClass, "JOB_FAIL_REASON__DOCUMENT_PASSWORD_ERROR",
788             "Ljava/lang/String;");
789     _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_PERMISSION_ERROR = (*env)->GetStaticFieldID(
790             env, _PrintServiceStringsClass, "JOB_FAIL_REASON__DOCUMENT_PERMISSION_ERROR",
791             "Ljava/lang/String;");
792     _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_SECURITY_ERROR = (*env)->GetStaticFieldID(
793             env, _PrintServiceStringsClass, "JOB_FAIL_REASON__DOCUMENT_SECURITY_ERROR",
794             "Ljava/lang/String;");
795     _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_UNPRINTABLE_ERROR =
796             (*env)->GetStaticFieldID(env, _PrintServiceStringsClass,
797             "JOB_FAIL_REASON__DOCUMENT_UNPRINTABLE_ERROR", "Ljava/lang/String;");
798     _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_ACCESS_ERROR = (*env)->GetStaticFieldID(
799             env, _PrintServiceStringsClass, "JOB_FAIL_REASON__DOCUMENT_ACCESS_ERROR",
800             "Ljava/lang/String;");
801     _PrintServiceStringField__JOB_FAIL_REASON__SUBMISSION_INTERRUPTED = (*env)->GetStaticFieldID(
802             env, _PrintServiceStringsClass, "JOB_FAIL_REASON__SUBMISSION_INTERRUPTED",
803             "Ljava/lang/String;");
804 
805     pdf_render_init(env);
806 }
807 
808 /*
809  * Converts java printer caps to c and saves them to wprintPrinterCaps
810  */
_convertPrinterCaps_to_C(JNIEnv * env,jobject javaPrinterCaps,printer_capabilities_t * wprintPrinterCaps)811 static int _convertPrinterCaps_to_C(JNIEnv *env, jobject javaPrinterCaps,
812         printer_capabilities_t *wprintPrinterCaps) {
813     if (!javaPrinterCaps || !wprintPrinterCaps) {
814         return ERROR;
815     }
816 
817     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
818             env, javaPrinterCaps, _LocalPrinterCapabilitiesField__nativeData);
819     if (!nativeDataObject) {
820         return ERROR;
821     }
822     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
823     memcpy(wprintPrinterCaps, (const void *) nativeDataPtr, sizeof(printer_capabilities_t));
824     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, 0);
825 
826     return OK;
827 }
828 
829 /*
830  * Converts printer caps to java and saves them to javaPrinterCaps
831  */
_convertPrinterCaps_to_Java(JNIEnv * env,jobject javaPrinterCaps,const printer_capabilities_t * wprintPrinterCaps)832 static int _convertPrinterCaps_to_Java(JNIEnv *env, jobject javaPrinterCaps,
833         const printer_capabilities_t *wprintPrinterCaps) {
834     if (!javaPrinterCaps || !wprintPrinterCaps) {
835         return ERROR;
836     }
837 
838     int arrayCreated = 0;
839     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
840             env, javaPrinterCaps, _LocalPrinterCapabilitiesField__nativeData);
841     if (!nativeDataObject) {
842         arrayCreated = 1;
843         nativeDataObject = (*env)->NewByteArray(env, sizeof(printer_capabilities_t));
844     }
845 
846     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
847     memcpy((void *) nativeDataPtr, wprintPrinterCaps, sizeof(printer_capabilities_t));
848     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, 0);
849 
850     if (arrayCreated) {
851         (*env)->SetObjectField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__nativeData,
852                 nativeDataObject);
853         (*env)->DeleteLocalRef(env, nativeDataObject);
854     }
855 
856     (*env)->SetBooleanField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__duplex,
857             (jboolean) wprintPrinterCaps->duplex);
858     (*env)->SetBooleanField(env, javaPrinterCaps,
859             _LocalPrinterCapabilitiesField__borderless,
860             (jboolean) wprintPrinterCaps->borderless);
861     (*env)->SetBooleanField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__color,
862             (jboolean) wprintPrinterCaps->color);
863     (*env)->SetBooleanField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__isSupported,
864             (jboolean) wprintPrinterCaps->isSupported);
865 
866     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__mediaDefault,
867             wprintPrinterCaps->mediaDefault);
868     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__path,
869             wprintPrinterCaps->printerUri);
870     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__name,
871             wprintPrinterCaps->name);
872     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__uuid,
873             wprintPrinterCaps->uuid);
874     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__location,
875             wprintPrinterCaps->location);
876 
877     jintArray intArray;
878     int *intArrayPtr;
879     int index;
880 
881     intArray = (*env)->NewIntArray(env, wprintPrinterCaps->numSupportedMediaTypes);
882     intArrayPtr = (*env)->GetIntArrayElements(env, intArray, NULL);
883     for (index = 0; index < wprintPrinterCaps->numSupportedMediaTypes; index++) {
884         intArrayPtr[index] = (int) wprintPrinterCaps->supportedMediaTypes[index];
885     }
886     (*env)->ReleaseIntArrayElements(env, intArray, intArrayPtr, 0);
887     (*env)->SetObjectField(env, javaPrinterCaps,
888             _LocalPrinterCapabilitiesField__supportedMediaTypes, intArray);
889     (*env)->DeleteLocalRef(env, intArray);
890 
891     intArray = (*env)->NewIntArray(env, wprintPrinterCaps->numSupportedMediaSizes);
892     intArrayPtr = (*env)->GetIntArrayElements(env, intArray, NULL);
893     for (index = 0; index < wprintPrinterCaps->numSupportedMediaSizes; index++) {
894         intArrayPtr[index] = (int) wprintPrinterCaps->supportedMediaSizes[index];
895     }
896     (*env)->ReleaseIntArrayElements(env, intArray, intArrayPtr, 0);
897     (*env)->SetObjectField(env, javaPrinterCaps,
898             _LocalPrinterCapabilitiesField__supportedMediaSizes, intArray);
899     (*env)->DeleteLocalRef(env, intArray);
900 
901     int count;
902     for (count = index = 0; index < (sizeof(int) * 8); index++) {
903         if ((wprintPrinterCaps->supportedInputMimeTypes & (1 << index)) != 0) {
904             count++;
905         }
906     }
907 
908     return OK;
909 }
910 
911 /*
912  * Converts str to a java string
913  */
stringToJava(JNIEnv * env,jobject obj,jfieldID id,const char * str)914 static void stringToJava(JNIEnv *env, jobject obj, jfieldID id, const char *str) {
915     jstring jStr;
916 
917     // If null, copy an empty string
918     if (!str) str = "";
919 
920     jStr = (*env)->NewStringUTF(env, str);
921     (*env)->SetObjectField(env, obj, id, jStr);
922     (*env)->DeleteLocalRef(env, jStr);
923 }
924 
925 /*
926  * Converts javaJobParams to C and saves them to wprintJobParams
927  */
_convertJobParams_to_C(JNIEnv * env,jobject javaJobParams,wprint_job_params_t * wprintJobParams)928 static int _convertJobParams_to_C(JNIEnv *env, jobject javaJobParams,
929         wprint_job_params_t *wprintJobParams) {
930     if (!javaJobParams || !wprintJobParams) {
931         return ERROR;
932     }
933 
934     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
935             env, javaJobParams, _LocalJobParamsField__nativeData);
936     if (nativeDataObject == 0) {
937         return ERROR;
938     }
939 
940     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
941     memcpy(wprintJobParams, (const void *) nativeDataPtr, sizeof(wprint_job_params_t));
942     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, JNI_ABORT);
943 
944     wprintJobParams->media_size = (media_size_t) (*env)->GetIntField(
945             env, javaJobParams, _LocalJobParamsField__media_size);
946     wprintJobParams->media_type = (media_type_t) (*env)->GetIntField(
947             env, javaJobParams, _LocalJobParamsField__media_type);
948     wprintJobParams->duplex = (duplex_t) (*env)->GetIntField(
949             env, javaJobParams, _LocalJobParamsField__duplex);
950     wprintJobParams->color_space = (color_space_t) (*env)->GetIntField(
951             env, javaJobParams, _LocalJobParamsField__color_space);
952     wprintJobParams->media_tray = (media_tray_t) (*env)->GetIntField(
953             env, javaJobParams, _LocalJobParamsField__media_tray);
954     wprintJobParams->num_copies = (unsigned int) (*env)->GetIntField(
955             env, javaJobParams, _LocalJobParamsField__num_copies);
956     wprintJobParams->borderless = (bool) (*env)->GetIntField(env, javaJobParams,
957             _LocalJobParamsField__borderless);
958     wprintJobParams->render_flags = (unsigned int) (*env)->GetIntField(
959             env, javaJobParams, _LocalJobParamsField__render_flags);
960     wprintJobParams->pdf_render_resolution =
961             (unsigned int) (*env)->GetIntField(env, javaJobParams,
962                     _LocalJobParamsField__pdf_render_resolution);
963     // job margin setting
964     wprintJobParams->job_top_margin = (float) (*env)->GetFloatField(
965             env, javaJobParams, _LocalJobParamsField__job_margin_top);
966     wprintJobParams->job_left_margin = (float) (*env)->GetFloatField(
967             env, javaJobParams, _LocalJobParamsField__job_margin_left);
968     wprintJobParams->job_right_margin = (float) (*env)->GetFloatField(
969             env, javaJobParams, _LocalJobParamsField__job_margin_right);
970     wprintJobParams->job_bottom_margin = (float) (*env)->GetFloatField(
971             env, javaJobParams, _LocalJobParamsField__job_margin_bottom);
972     wprintJobParams->source_height = (float) (*env)->GetFloatField(
973             env, javaJobParams, _LocalJobParamsField__source_height);
974     wprintJobParams->source_width = (float) (*env)->GetFloatField(
975             env, javaJobParams, _LocalJobParamsField__source_width);
976     wprintJobParams->preserve_scaling = (bool) (*env)->GetBooleanField(env, javaJobParams,
977             _LocalJobParamsField__preserve_scaling);
978 
979     if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__portrait_mode)) {
980         wprintJobParams->render_flags |= RENDER_FLAG_PORTRAIT_MODE;
981     } else if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__landscape_mode)) {
982         wprintJobParams->render_flags |= RENDER_FLAG_LANDSCAPE_MODE;
983     } else if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__auto_rotate)) {
984         wprintJobParams->render_flags |= RENDER_FLAG_AUTO_ROTATE;
985     }
986     if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__fill_page)) {
987         wprintJobParams->render_flags |= AUTO_SCALE_RENDER_FLAGS;
988     } else if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__fit_to_page)) {
989         wprintJobParams->render_flags |= AUTO_FIT_RENDER_FLAGS;
990         if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__document_scaling)) {
991             wprintJobParams->render_flags |= RENDER_FLAG_DOCUMENT_SCALING;
992         }
993     }
994 
995     int alignment = ((*env)->GetIntField(env, javaJobParams, _LocalJobParamsField__alignment));
996     if (alignment != 0) {
997         LOGD("Alignment value %d", alignment);
998         wprintJobParams->render_flags &= ~(RENDER_FLAG_CENTER_VERTICAL |
999                 RENDER_FLAG_CENTER_HORIZONTAL |
1000                 RENDER_FLAG_CENTER_ON_ORIENTATION);
1001         if (alignment & ((*env)->GetStaticIntField(
1002                 env, _PrintServiceStringsClass,
1003                 _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL))) {
1004             wprintJobParams->render_flags |= RENDER_FLAG_CENTER_HORIZONTAL;
1005         }
1006         if (alignment & ((*env)->GetStaticIntField(
1007                 env, _PrintServiceStringsClass,
1008                 _PrintServiceStringsField__ALIGNMENT__CENTER_VERTICAL))) {
1009             wprintJobParams->render_flags |= RENDER_FLAG_CENTER_VERTICAL;
1010         }
1011         if (alignment & ((*env)->GetStaticIntField(
1012                 env, _PrintServiceStringsClass,
1013                 _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL_ON_ORIENTATION))) {
1014             wprintJobParams->render_flags |= RENDER_FLAG_CENTER_ON_ORIENTATION;
1015         }
1016         if ((alignment & ((*env)->GetStaticIntField(
1017                 env, _PrintServiceStringsClass, _PrintServiceStringsField__ALIGNMENT__CENTER))) ==
1018                 ((*env)->GetStaticIntField(env, _PrintServiceStringsClass,
1019                         _PrintServiceStringsField__ALIGNMENT__CENTER))) {
1020             wprintJobParams->render_flags &= ~RENDER_FLAG_CENTER_ON_ORIENTATION;
1021             wprintJobParams->render_flags |= (RENDER_FLAG_CENTER_VERTICAL |
1022                     RENDER_FLAG_CENTER_HORIZONTAL);
1023         }
1024     }
1025 
1026     jstring docCategory = (jstring) (*env)->GetObjectField(env, javaJobParams,
1027             _LocalJobParamsField__document_category);
1028     if (docCategory != NULL) {
1029         const char *category = (*env)->GetStringUTFChars(env, docCategory, NULL);
1030         if (category != NULL) {
1031             strncpy(wprintJobParams->docCategory, category,
1032                     sizeof(wprintJobParams->docCategory) - 1);
1033             (*env)->ReleaseStringUTFChars(env, docCategory, category);
1034         }
1035     }
1036     // job name
1037     jstring jobName = (jstring) (*env)->GetObjectField(env, javaJobParams,
1038             _LocalJobParamsField__job_name);
1039     if (jobName != NULL) {
1040         const char *name = (*env)->GetStringUTFChars(env, jobName, NULL);
1041         if (name != NULL) {
1042             strncpy(wprintJobParams->job_name, name, sizeof(wprintJobParams->job_name) - 1);
1043             (*env)->ReleaseStringUTFChars(env, jobName, name);
1044         }
1045     }
1046     // job originating user name
1047     jstring jobOriginatingUserName = (jstring) (*env)->GetObjectField(
1048             env, javaJobParams, _LocalJobParamsField__job_originating_user_name);
1049     if (jobOriginatingUserName != NULL) {
1050         const char *name = (*env)->GetStringUTFChars(env, jobOriginatingUserName, NULL);
1051         if (name != NULL) {
1052             strncpy(wprintJobParams->job_originating_user_name, name,
1053                     sizeof(wprintJobParams->job_originating_user_name) - 1);
1054             (*env)->ReleaseStringUTFChars(env, jobOriginatingUserName, name);
1055         }
1056     }
1057 
1058     free(wprintJobParams->page_range);
1059     wprintJobParams->page_range = NULL;
1060     jstring pageRangeObject = (jstring) (*env)->GetObjectField(env, javaJobParams,
1061             _LocalJobParamsField__page_range);
1062     if (pageRangeObject) {
1063         int page_range_size = (*env)->GetStringLength(env, pageRangeObject);
1064         const jbyte *pageRange = (jbyte *) (*env)->GetStringUTFChars(env, pageRangeObject, 0);
1065         if (strcmp((char *) pageRange, "") != 0) {
1066             wprintJobParams->page_range = (char *) malloc(page_range_size + 1);
1067             memset(wprintJobParams->page_range, 0, page_range_size + 1);
1068             strncpy(wprintJobParams->page_range, (char *) pageRange, page_range_size);
1069 
1070             (*env)->ReleaseStringUTFChars(env, pageRangeObject, (const char *) pageRange);
1071         }
1072     }
1073 
1074     return OK;
1075 }
1076 
1077 /*
1078  * Converts wprintJobParams to java and saves them to javaJobParams
1079  */
_covertJobParams_to_Java(JNIEnv * env,jobject javaJobParams,wprint_job_params_t * wprintJobParams)1080 static int _covertJobParams_to_Java(JNIEnv *env, jobject javaJobParams,
1081         wprint_job_params_t *wprintJobParams) {
1082     if (!javaJobParams || !wprintJobParams) {
1083         return ERROR;
1084     }
1085 
1086     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
1087             env, javaJobParams, _LocalJobParamsField__nativeData);
1088     if (!nativeDataObject) {
1089         nativeDataObject = (*env)->NewByteArray(env, sizeof(wprint_job_params_t));
1090         (*env)->SetObjectField(env, javaJobParams, _LocalJobParamsField__nativeData,
1091                 nativeDataObject);
1092         nativeDataObject = (jbyteArray) (*env)->GetObjectField(env, javaJobParams,
1093                 _LocalJobParamsField__nativeData);
1094     }
1095 
1096     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
1097     memcpy((void *) nativeDataPtr, wprintJobParams, sizeof(wprint_job_params_t));
1098     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, 0);
1099 
1100     // update job parameters
1101     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__media_size,
1102             (int) wprintJobParams->media_size);
1103     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__media_type,
1104             (int) wprintJobParams->media_type);
1105     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__duplex,
1106             (int) wprintJobParams->duplex);
1107     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__color_space,
1108             (int) wprintJobParams->color_space);
1109     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__media_tray,
1110             (int) wprintJobParams->media_tray);
1111     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__num_copies,
1112             (int) wprintJobParams->num_copies);
1113     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__borderless,
1114             (int) wprintJobParams->borderless);
1115     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__render_flags,
1116             (int) wprintJobParams->render_flags);
1117     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__pdf_render_resolution,
1118             wprintJobParams->pdf_render_resolution);
1119     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__fit_to_page,
1120             (jboolean) ((wprintJobParams->render_flags & AUTO_FIT_RENDER_FLAGS) ==
1121                     AUTO_FIT_RENDER_FLAGS));
1122     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__fill_page,
1123             (jboolean) ((wprintJobParams->render_flags & AUTO_SCALE_RENDER_FLAGS) ==
1124                     AUTO_SCALE_RENDER_FLAGS));
1125     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__auto_rotate,
1126             (jboolean) ((wprintJobParams->render_flags & RENDER_FLAG_AUTO_ROTATE) != 0));
1127     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__portrait_mode, (jboolean) (
1128             (wprintJobParams->render_flags & RENDER_FLAG_PORTRAIT_MODE) != 0));
1129     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__landscape_mode, (jboolean) (
1130             (wprintJobParams->render_flags & RENDER_FLAG_LANDSCAPE_MODE) != 0));
1131     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__preserve_scaling,
1132             (jboolean) (wprintJobParams->preserve_scaling));
1133 
1134     // update the printable area & DPI information
1135     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__print_resolution,
1136             (int) wprintJobParams->pixel_units);
1137     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__printable_width,
1138             (int) wprintJobParams->width);
1139     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__printable_height,
1140             (int) wprintJobParams->height);
1141 
1142     // update the page size information
1143     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_width,
1144             wprintJobParams->page_width);
1145     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_height,
1146             wprintJobParams->page_height);
1147     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_top,
1148             wprintJobParams->page_top_margin);
1149     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_left,
1150             wprintJobParams->page_left_margin);
1151     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_right,
1152             wprintJobParams->page_right_margin);
1153     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_bottom,
1154             wprintJobParams->page_bottom_margin);
1155 
1156     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_top,
1157             wprintJobParams->job_top_margin);
1158     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_left,
1159             wprintJobParams->job_left_margin);
1160     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_right,
1161             wprintJobParams->job_right_margin);
1162     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_bottom,
1163             wprintJobParams->job_bottom_margin);
1164     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__source_width,
1165             wprintJobParams->source_width);
1166     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__source_height,
1167             wprintJobParams->source_height);
1168 
1169     return OK;
1170 }
1171 
1172 /*
1173  * Process fail reasons. Converts them to strings from BackendConstants.java
1174  */
processFailReasons(JNIEnv * env,unsigned long long fail_reasons,unsigned int count)1175 static jobjectArray processFailReasons(JNIEnv *env, unsigned long long fail_reasons,
1176                                        unsigned int count) {
1177     LOGI("entering _process_fail_reasons()");
1178     unsigned int i, reasonCount;
1179 
1180     jstring jStr = (*env)->NewStringUTF(env, "");
1181     jobjectArray stringArray = (*env)->NewObjectArray(env, count,
1182                                                       (*env)->FindClass(env, "java/lang/String"),
1183                                                       jStr);
1184     (*env)->DeleteLocalRef(env, jStr);
1185 
1186     // Note : The fail reason determination conditions should appear in the same sequence
1187     // as defined by enum job_state_reason_t from which they are derived from
1188 
1189     for (reasonCount = i = 0; i < IPP_JOB_STATE_REASON_MAX_VALUE; i++) {
1190         jStr = NULL;
1191 
1192         if ((fail_reasons & (LONG_ONE << i)) == 0) {
1193             jStr = NULL;
1194         } else if (fail_reasons & JOB_FAIL_REASON_UNABLE_TO_CONNECT) {
1195             jStr = (jstring) (*env)->
1196                     GetStaticObjectField(env, _PrintServiceStringsClass,
1197                                          _PrintServiceStringsField__BLOCKED_REASON__OFFLINE);
1198         } else if (fail_reasons & JOB_FAIL_REASON_ABORTED_BY_SYSTEM) {
1199             jStr = (jstring) (*env)->
1200                     GetStaticObjectField(env, _PrintServiceStringsClass,
1201                                      _PrintServiceStringField__JOB_FAIL_REASON__ABORTED_BY_SYSTEM);
1202         } else if (fail_reasons & JOB_FAIL_REASON_UNSUPPORTED_COMPRESSION) {
1203             jStr = (jstring) (*env)->
1204                     GetStaticObjectField(env, _PrintServiceStringsClass,
1205                              _PrintServiceStringField__JOB_FAIL_REASON__UNSUPPORTED_COMPRESSION);
1206         } else if (fail_reasons & JOB_FAIL_REASON_COMPRESSION_ERROR) {
1207             jStr = (jstring) (*env)->
1208                     GetStaticObjectField(env, _PrintServiceStringsClass,
1209                                    _PrintServiceStringField__JOB_FAIL_REASON__COMPRESSION_ERROR);
1210         } else if (fail_reasons & JOB_FAIL_REASON_UNSUPPORTED_DOCUMENT_FORMAT) {
1211             jStr = (jstring) (*env)->
1212                     GetStaticObjectField(env, _PrintServiceStringsClass,
1213                            _PrintServiceStringField__JOB_FAIL_REASON__UNSUPPORTED_DOCUMENT_FORMAT);
1214         } else if (fail_reasons & JOB_FAIL_REASON_DOCUMENT_FORMAT_ERROR) {
1215             jStr = (jstring) (*env)->
1216                     GetStaticObjectField(env, _PrintServiceStringsClass,
1217                                _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_FORMAT_ERROR);
1218         } else if (fail_reasons & JOB_FAIL_REASON_SERVICE_OFFLINE) {
1219             jStr = (jstring) (*env)->
1220                     GetStaticObjectField(env, _PrintServiceStringsClass,
1221                                        _PrintServiceStringField__JOB_FAIL_REASON__SERVICE_OFFLINE);
1222         } else if (fail_reasons & JOB_FAIL_REASON_DOCUMENT_PASSWORD_ERROR) {
1223             jStr = (jstring) (*env)->
1224                     GetStaticObjectField(env, _PrintServiceStringsClass,
1225                               _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_PASSWORD_ERROR);
1226         } else if (fail_reasons & JOB_FAIL_REASON_DOCUMENT_PERMISSION_ERROR) {
1227             jStr = (jstring) (*env)->
1228                     GetStaticObjectField(env, _PrintServiceStringsClass,
1229                               _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_PERMISSION_ERROR);
1230         } else if (fail_reasons & JOB_FAIL_REASON_DOCUMENT_SECURITY_ERROR) {
1231             jStr = (jstring) (*env)->
1232                     GetStaticObjectField(env, _PrintServiceStringsClass,
1233                               _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_SECURITY_ERROR);
1234         } else if (fail_reasons & JOB_FAIL_REASON_DOCUMENT_UNPRINTABLE_ERROR) {
1235             jStr = (jstring) (*env)->
1236                     GetStaticObjectField(env, _PrintServiceStringsClass,
1237                           _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_UNPRINTABLE_ERROR);
1238         } else if (fail_reasons & JOB_FAIL_REASON_DOCUMENT_ACCESS_ERROR) {
1239             jStr = (jstring) (*env)->
1240                     GetStaticObjectField(env, _PrintServiceStringsClass,
1241                                  _PrintServiceStringField__JOB_FAIL_REASON__DOCUMENT_ACCESS_ERROR);
1242         } else if (fail_reasons & JOB_FAIL_REASON_SUBMISSION_INTERRUPTED) {
1243             jStr = (jstring) (*env)->
1244                     GetStaticObjectField(env, _PrintServiceStringsClass,
1245                                  _PrintServiceStringField__JOB_FAIL_REASON__SUBMISSION_INTERRUPTED);
1246         } else if (fail_reasons & JOB_FAIL_REASON_AUTHORIZATION_FAILED) {
1247             jStr = (jstring) (*env)->
1248                     GetStaticObjectField(env, _PrintServiceStringsClass,
1249                                          _PrintServiceStringsField__JOB_DONE_AUTHORIZATION_FAILED);
1250         } else if (fail_reasons & JOB_FAIL_REASON_ACCOUNT_CLOSED) {
1251             jStr = (jstring) (*env)->
1252                     GetStaticObjectField(env, _PrintServiceStringsClass,
1253                                          _PrintServiceStringsField__JOB_DONE_ACCOUNT_CLOSED);
1254         } else if (fail_reasons & JOB_FAIL_REASON_ACCOUNT_INFO_NEEDED) {
1255             jStr = (jstring) (*env)->
1256                     GetStaticObjectField(env, _PrintServiceStringsClass,
1257                                          _PrintServiceStringsField__JOB_DONE_ACCOUNT_INFO_NEEDED);
1258         } else if (fail_reasons & JOB_FAIL_REASON_ACCOUNT_LIMIT_REACHED) {
1259             jStr = (jstring) (*env)->
1260                     GetStaticObjectField(env, _PrintServiceStringsClass,
1261                                          _PrintServiceStringsField__JOB_DONE_ACCOUNT_LIMIT_REACHED);
1262         }
1263 
1264         fail_reasons &= ~(LONG_ONE << i);
1265 
1266         if (jStr != NULL) {
1267             (*env)->SetObjectArrayElement(env, stringArray, reasonCount++, jStr);
1268         }
1269     }
1270     return stringArray;
1271 }
1272 
1273 /*
1274  * Process block status. Converts the blocked reasons to strings from BackendConstants.java
1275  */
processBlockStatus(JNIEnv * env,unsigned long long blocked_reasons,unsigned int count)1276 static jobjectArray processBlockStatus(JNIEnv *env, unsigned long long blocked_reasons,
1277                                        unsigned int count) {
1278     LOGI("entering process_block_status()");
1279     unsigned int i, reasonCount;
1280 
1281     jstring jStr = (*env)->NewStringUTF(env, "");
1282     jobjectArray stringArray = (*env)->NewObjectArray(env, count,
1283                                                       (*env)->FindClass(env, "java/lang/String"),
1284                                                       jStr);
1285     (*env)->DeleteLocalRef(env, jStr);
1286 
1287     // Note : The block reason determination  conditions should appear in the same sequence
1288     // as defined by enum print_status_t from which they are derived from
1289     for (reasonCount = i = 0; i < PRINT_STATUS_MAX_STATE; i++) {
1290         jStr = NULL;
1291 
1292         if ((blocked_reasons & (LONG_ONE << i)) == 0) {
1293             jStr = NULL;
1294         } else if (blocked_reasons & BLOCKED_REASON_UNABLE_TO_CONNECT) {
1295             jStr = (jstring) (*env)->
1296                     GetStaticObjectField(env, _PrintServiceStringsClass,
1297                                          _PrintServiceStringsField__BLOCKED_REASON__OFFLINE);
1298         } else if (blocked_reasons & BLOCKED_REASON_BUSY) {
1299             jStr = (jstring) (*env)->
1300                     GetStaticObjectField(env, _PrintServiceStringsClass,
1301                                           _PrintServiceStringsField__BLOCKED_REASON__BUSY);
1302         } else if (blocked_reasons & BLOCKED_REASONS_CANCELLED) {
1303             jStr = (jstring) (*env)->
1304                     GetStaticObjectField(env, _PrintServiceStringsClass,
1305                                          _PrintServiceStringsField__BLOCKED_REASON__CANCELLED);
1306         } else if (blocked_reasons & BLOCKED_REASON_OUT_OF_PAPER) {
1307             jStr = (jstring) (*env)->
1308                     GetStaticObjectField(env, _PrintServiceStringsClass,
1309                                          _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_PAPER);
1310         } else if (blocked_reasons & BLOCKED_REASON_OUT_OF_INK) {
1311             jStr = (jstring) (*env)->
1312                     GetStaticObjectField(env, _PrintServiceStringsClass,
1313                                          _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_INK);
1314         } else if (blocked_reasons & BLOCKED_REASON_OUT_OF_TONER) {
1315             jStr = (jstring) (*env)->
1316                     GetStaticObjectField(env, _PrintServiceStringsClass,
1317                                          _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_TONER);
1318         } else if (blocked_reasons & BLOCKED_REASON_JAMMED) {
1319             jStr = (jstring) (*env)->
1320                     GetStaticObjectField(env, _PrintServiceStringsClass,
1321                                          _PrintServiceStringsField__BLOCKED_REASON__JAMMED);
1322         } else if (blocked_reasons & BLOCKED_REASON_DOOR_OPEN) {
1323             jStr = (jstring) (*env)->
1324                     GetStaticObjectField(env, _PrintServiceStringsClass,
1325                                          _PrintServiceStringsField__BLOCKED_REASON__DOOR_OPEN);
1326         } else if (blocked_reasons & BLOCKED_REASON_SVC_REQUEST) {
1327             jStr = (jstring) (*env)->
1328                     GetStaticObjectField(env, _PrintServiceStringsClass,
1329                                      _PrintServiceStringsField__BLOCKED_REASON__SERVICE_REQUEST);
1330         } else if (blocked_reasons & BLOCKED_REASON_PAUSED) {
1331             jStr = (jstring) (*env)->
1332                     GetStaticObjectField(env, _PrintServiceStringsClass,
1333                                          _PrintServiceStringsField__BLOCKED_REASON__PAUSED);
1334         } else if (blocked_reasons & BLOCKED_REASON_STOPPED) {
1335             jStr = (jstring) (*env)->
1336                     GetStaticObjectField(env, _PrintServiceStringsClass,
1337                                          _PrintServiceStringsField__BLOCKED_REASON__STOPPED);
1338         } else if (blocked_reasons & BLOCKED_REASON_LOW_ON_INK) {
1339             jStr = (jstring) (*env)->
1340                     GetStaticObjectField(env, _PrintServiceStringsClass,
1341                                          _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_INK);
1342         } else if (blocked_reasons & BLOCKED_REASON_LOW_ON_TONER) {
1343             jStr = (jstring) (*env)->
1344                     GetStaticObjectField(env, _PrintServiceStringsClass,
1345                                          _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_TONER);
1346         } else if (blocked_reasons & BLOCKED_REASON_INPUT_CANNOT_FEED_SIZE_SELECTED) {
1347             jStr = (jstring) (*env)->
1348                     GetStaticObjectField(env, _PrintServiceStringsClass,
1349                         _PrintServiceStringsField__BLOCKED_REASON__INPUT_CANNOT_FEED_SIZE_SELECTED);
1350         } else if (blocked_reasons & BLOCKED_REASON_INTERLOCK_ERROR) {
1351             jStr = (jstring) (*env)->
1352                     GetStaticObjectField(env, _PrintServiceStringsClass,
1353                                      _PrintServiceStringsField__BLOCKED_REASON__INTERLOCK_ERROR);
1354         } else if (blocked_reasons & BLOCKED_REASON_OUTPUT_TRAY_MISSING) {
1355             jStr = (jstring) (*env)->
1356                     GetStaticObjectField(env, _PrintServiceStringsClass,
1357                                  _PrintServiceStringsField__BLOCKED_REASON__OUTPUT_TRAY_MISSING);
1358         } else if (blocked_reasons & BLOCKED_REASON_BANDER_ERROR) {
1359             jStr = (jstring) (*env)->
1360                     GetStaticObjectField(env, _PrintServiceStringsClass,
1361                                          _PrintServiceStringsField__BLOCKED_REASON__BANDER_ERROR);
1362         } else if (blocked_reasons & BLOCKED_REASON_BINDER_ERROR) {
1363             jStr = (jstring) (*env)->
1364                     GetStaticObjectField(env, _PrintServiceStringsClass,
1365                                          _PrintServiceStringsField__BLOCKED_REASON__BINDER_ERROR);
1366         } else if (blocked_reasons & BLOCKED_REASON_POWER_ERROR) {
1367             jStr = (jstring) (*env)->
1368                     GetStaticObjectField(env, _PrintServiceStringsClass,
1369                                          _PrintServiceStringsField__BLOCKED_REASON__POWER_ERROR);
1370         } else if (blocked_reasons & BLOCKED_REASON_CLEANER_ERROR) {
1371             jStr = (jstring) (*env)->
1372                     GetStaticObjectField(env, _PrintServiceStringsClass,
1373                                          _PrintServiceStringsField__BLOCKED_REASON__CLEANER_ERROR);
1374         } else if (blocked_reasons & BLOCKED_REASON_INPUT_TRAY_ERROR) {
1375             jStr = (jstring) (*env)->
1376                     GetStaticObjectField(env, _PrintServiceStringsClass,
1377                                      _PrintServiceStringsField__BLOCKED_REASON__INPUT_TRAY_ERROR);
1378         } else if (blocked_reasons & BLOCKED_REASON_INSERTER_ERROR) {
1379             jStr = (jstring) (*env)->
1380                     GetStaticObjectField(env, _PrintServiceStringsClass,
1381                                          _PrintServiceStringsField__BLOCKED_REASON__INSERTER_ERROR);
1382         } else if (blocked_reasons & BLOCKED_REASON_INTERPRETER_ERROR) {
1383             jStr = (jstring) (*env)->
1384                     GetStaticObjectField(env, _PrintServiceStringsClass,
1385                                      _PrintServiceStringsField__BLOCKED_REASON__INTERPRETER_ERROR);
1386         } else if (blocked_reasons & BLOCKED_REASON_MAKE_ENVELOPE_ERROR) {
1387             jStr = (jstring) (*env)->
1388                     GetStaticObjectField(env, _PrintServiceStringsClass,
1389                                  _PrintServiceStringsField__BLOCKED_REASON__MAKE_ENVELOPE_ERROR);
1390         } else if (blocked_reasons & BLOCKED_REASON_MARKER_ERROR) {
1391             jStr = (jstring) (*env)->
1392                     GetStaticObjectField(env, _PrintServiceStringsClass,
1393                                          _PrintServiceStringsField__BLOCKED_REASON__MARKER_ERROR);
1394         } else if (blocked_reasons & BLOCKED_REASON_MEDIA_ERROR) {
1395             jStr = (jstring) (*env)->
1396                     GetStaticObjectField(env, _PrintServiceStringsClass,
1397                                          _PrintServiceStringsField__BLOCKED_REASON__MEDIA_ERROR);
1398         } else if (blocked_reasons & BLOCKED_REASON_PERFORATER_ERROR) {
1399             jStr = (jstring) (*env)->
1400                     GetStaticObjectField(env, _PrintServiceStringsClass,
1401                                      _PrintServiceStringsField__BLOCKED_REASON__PERFORATER_ERROR);
1402         } else if (blocked_reasons & BLOCKED_REASON_PUNCHER_ERROR) {
1403             jStr = (jstring) (*env)->
1404                     GetStaticObjectField(env, _PrintServiceStringsClass,
1405                                          _PrintServiceStringsField__BLOCKED_REASON__PUNCHER_ERROR);
1406         } else if (blocked_reasons & BLOCKED_REASON_SEPARATION_CUTTER_ERROR) {
1407             jStr = (jstring) (*env)->
1408                     GetStaticObjectField(env, _PrintServiceStringsClass,
1409                              _PrintServiceStringsField__BLOCKED_REASON__SEPARATION_CUTTER_ERROR);
1410         } else if (blocked_reasons & BLOCKED_REASON_SHEET_ROTATOR_ERROR) {
1411             jStr = (jstring) (*env)->
1412                     GetStaticObjectField(env, _PrintServiceStringsClass,
1413                                  _PrintServiceStringsField__BLOCKED_REASON__SHEET_ROTATOR_ERROR);
1414         } else if (blocked_reasons & BLOCKED_REASON_SLITTER_ERROR) {
1415             jStr = (jstring) (*env)->
1416                     GetStaticObjectField(env, _PrintServiceStringsClass,
1417                                          _PrintServiceStringsField__BLOCKED_REASON__SLITTER_ERROR);
1418         } else if (blocked_reasons & BLOCKED_REASON_STACKER_ERROR) {
1419             jStr = (jstring) (*env)->
1420                     GetStaticObjectField(env, _PrintServiceStringsClass,
1421                                          _PrintServiceStringsField__BLOCKED_REASON__STACKER_ERROR);
1422         } else if (blocked_reasons & BLOCKED_REASON_STAPLER_ERROR) {
1423             jStr = (jstring) (*env)->
1424                     GetStaticObjectField(env, _PrintServiceStringsClass,
1425                                          _PrintServiceStringsField__BLOCKED_REASON__STAPLER_ERROR);
1426         } else if (blocked_reasons & BLOCKED_REASON_STITCHER_ERROR) {
1427             jStr = (jstring) (*env)->
1428                     GetStaticObjectField(env, _PrintServiceStringsClass,
1429                                          _PrintServiceStringsField__BLOCKED_REASON__STITCHER_ERROR);
1430         } else if (blocked_reasons & BLOCKED_REASON_SUBUNIT_ERROR) {
1431             jStr = (jstring) (*env)->
1432                     GetStaticObjectField(env, _PrintServiceStringsClass,
1433                                          _PrintServiceStringsField__BLOCKED_REASON__SUBUNIT_ERROR);
1434         } else if (blocked_reasons & BLOCKED_REASON_TRIMMER_ERROR) {
1435             jStr = (jstring) (*env)->
1436                     GetStaticObjectField(env, _PrintServiceStringsClass,
1437                                          _PrintServiceStringsField__BLOCKED_REASON__TRIMMER_ERROR);
1438         } else if (blocked_reasons & BLOCKED_REASON_WRAPPER_ERROR) {
1439             jStr = (jstring) (*env)->
1440                     GetStaticObjectField(env, _PrintServiceStringsClass,
1441                                          _PrintServiceStringsField__BLOCKED_REASON__WRAPPER_ERROR);
1442         } else if (blocked_reasons & BLOCKED_REASON_CLIENT_ERROR) {
1443             jStr = (jstring) (*env)->
1444                     GetStaticObjectField(env, _PrintServiceStringsClass,
1445                                          _PrintServiceStringsField__BLOCKED_REASON__CLIENT_ERROR);
1446         } else if (blocked_reasons & BLOCKED_REASON_SERVER_ERROR) {
1447             jStr = (jstring) (*env)->
1448                     GetStaticObjectField(env, _PrintServiceStringsClass,
1449                                          _PrintServiceStringsField__BLOCKED_REASON__SERVER_ERROR);
1450         } else if (blocked_reasons & BLOCKED_REASON_ALERT_REMOVAL_OF_BINARY_CHANGE_ENTRY) {
1451             jStr = (jstring) (*env)->
1452                     GetStaticObjectField(
1453                             env,
1454                             _PrintServiceStringsClass,
1455                      _PrintServiceStringsField__BLOCKED_REASON__ALERT_REMOVAL_OF_BINARY_CHANGE_ENTRY
1456                    );
1457         } else if (blocked_reasons & BLOCKED_REASON_CONFIGURATION_CHANGED) {
1458             jStr = (jstring) (*env)->
1459                     GetStaticObjectField(env, _PrintServiceStringsClass,
1460                                  _PrintServiceStringsField__BLOCKED_REASON__CONFIGURATION_CHANGED);
1461         } else if (blocked_reasons & BLOCKED_REASON_CONNECTING_TO_DEVICE) {
1462             jStr = (jstring) (*env)->
1463                     GetStaticObjectField(env, _PrintServiceStringsClass,
1464                                  _PrintServiceStringsField__BLOCKED_REASON__CONNECTING_TO_DEVICE);
1465         } else if (blocked_reasons & BLOCKED_REASON_DEVELOPER_ERROR) {
1466             jStr = (jstring) (*env)->
1467                 GetStaticObjectField(env, _PrintServiceStringsClass,
1468                                      _PrintServiceStringsField__BLOCKED_REASON__DEVELOPER_ERROR);
1469         } else if (blocked_reasons & BLOCKED_REASON_HOLD_NEW_JOBS) {
1470             jStr = (jstring) (*env)->
1471                     GetStaticObjectField(env, _PrintServiceStringsClass,
1472                                          _PrintServiceStringsField__BLOCKED_REASON__HOLD_NEW_JOBS);
1473         } else if (blocked_reasons & BLOCKED_REASON_OPC_LIFE_OVER) {
1474             jStr = (jstring) (*env)->
1475                     GetStaticObjectField(env, _PrintServiceStringsClass,
1476                                          _PrintServiceStringsField__BLOCKED_REASON__OPC_LIFE_OVER);
1477         } else if (blocked_reasons & BLOCKED_REASON_SPOOL_AREA_FULL) {
1478             jStr = (jstring) (*env)->
1479                     GetStaticObjectField(env, _PrintServiceStringsClass,
1480                                      _PrintServiceStringsField__BLOCKED_REASON__SPOOL_AREA_FULL);
1481         } else if (blocked_reasons & BLOCKED_REASON_TIMED_OUT) {
1482             jStr = (jstring) (*env)->
1483                     GetStaticObjectField(env, _PrintServiceStringsClass,
1484                                          _PrintServiceStringsField__BLOCKED_REASON__TIMED_OUT);
1485         } else if (blocked_reasons & BLOCKED_REASON_SHUTDOWN) {
1486             jStr = (jstring) (*env)->
1487                     GetStaticObjectField(env, _PrintServiceStringsClass,
1488                                          _PrintServiceStringsField__BLOCKED_REASON__SHUTDOWN);
1489         } else if (blocked_reasons & BLOCKED_REASON_PRINTER_MANUAL_RESET) {
1490             jStr = (jstring) (*env)->
1491                     GetStaticObjectField(env, _PrintServiceStringsClass,
1492                                  _PrintServiceStringsField__BLOCKED_REASON__PRINTER_MANUAL_RESET);
1493         } else if (blocked_reasons & BLOCKED_REASON_PRINTER_NMS_RESET) {
1494             jStr = (jstring) (*env)->
1495                     GetStaticObjectField(env, _PrintServiceStringsClass,
1496                                      _PrintServiceStringsField__BLOCKED_REASON__PRINTER_NMS_RESET);
1497         }
1498 
1499         blocked_reasons &= ~(LONG_ONE << i);
1500 
1501         if (jStr != NULL) {
1502             (*env)->SetObjectArrayElement(env, stringArray, reasonCount++, jStr);
1503         }
1504     }
1505     return stringArray;
1506 }
1507 
1508 /*
1509  * Handles print job callbacks. Handles job states and blocked reasons
1510  */
_wprint_callback_fn(wJob_t job_handle,void * param)1511 static void _wprint_callback_fn(wJob_t job_handle, void *param) {
1512     jstring jStr;
1513     wprint_job_callback_params_t *cb_param = (wprint_job_callback_params_t *) param;
1514     if (!cb_param) {
1515         return;
1516     }
1517 
1518     int needDetach = 0;
1519     JNIEnv *env;
1520     if ((*_JVM)->GetEnv(_JVM, (void **) &env, JNI_VERSION_1_6) < 0) {
1521         needDetach = 1;
1522         if ((*_JVM)->AttachCurrentThread(_JVM, &env, NULL) < 0) {
1523             return;
1524         }
1525     }
1526 
1527     jobject callbackParams = (*env)->NewObject(env, _JobCallbackParamsClass,
1528             _JobCallbackParamsMethod__init);
1529     if (callbackParams != 0) {
1530         switch (cb_param->param.state) {
1531             case JOB_QUEUED:
1532                 jStr = (jstring) (*env)->GetStaticObjectField(
1533                         env, _PrintServiceStringsClass,
1534                         _PrintServiceStringsField__JOB_STATE_QUEUED);
1535                 break;
1536             case JOB_RUNNING:
1537                 jStr = (jstring) (*env)->GetStaticObjectField(
1538                         env, _PrintServiceStringsClass,
1539                         _PrintServiceStringsField__JOB_STATE_RUNNING);
1540                 break;
1541             case JOB_BLOCKED:
1542                 jStr = (jstring) (*env)->GetStaticObjectField(
1543                         env, _PrintServiceStringsClass,
1544                         _PrintServiceStringsField__JOB_STATE_BLOCKED);
1545                 break;
1546             case JOB_DONE:
1547                 jStr = (jstring) (*env)->GetStaticObjectField(
1548                         env, _PrintServiceStringsClass,
1549                         _PrintServiceStringsField__JOB_STATE_DONE);
1550                 break;
1551             default:
1552                 jStr = (jstring) (*env)->GetStaticObjectField(
1553                         env, _PrintServiceStringsClass,
1554                         _PrintServiceStringsField__JOB_STATE_OTHER);
1555                 break;
1556         }
1557         (*env)->SetObjectField(env, callbackParams, _JobCallbackParamsField__jobState, jStr);
1558 
1559         bool print_job_failed = false;
1560         if (cb_param->param.state == JOB_DONE) {
1561             switch (cb_param->job_done_result) {
1562                 case OK:
1563                     jStr = (jstring) (*env)->GetStaticObjectField(
1564                             env, _PrintServiceStringsClass,
1565                             _PrintServiceStringsField__JOB_DONE_OK);
1566                     break;
1567                 case ERROR:
1568                     print_job_failed = true;
1569                     jStr = (jstring) (*env)->GetStaticObjectField(
1570                             env, _PrintServiceStringsClass,
1571                             _PrintServiceStringsField__JOB_DONE_ERROR);
1572                     break;
1573                 case CANCELLED:
1574                     jStr = (jstring) (*env)->GetStaticObjectField(
1575                             env, _PrintServiceStringsClass,
1576                             _PrintServiceStringsField__JOB_DONE_CANCELLED);
1577                     break;
1578                 case CORRUPT:
1579                     print_job_failed = true;
1580                     jStr = (jstring) (*env)->GetStaticObjectField(
1581                             env, _PrintServiceStringsClass,
1582                             _PrintServiceStringsField__JOB_DONE_CORRUPT);
1583                     break;
1584                 case BAD_CERTIFICATE:
1585                     jStr = (jstring) (*env)->GetStaticObjectField(
1586                             env, _PrintServiceStringsClass,
1587                             _PrintServiceStringsField__JOB_DONE_BAD_CERTIFICATE);
1588                     break;
1589                 default:
1590                     jStr = (jstring) (*env)->GetStaticObjectField(
1591                             env, _PrintServiceStringsClass,
1592                             _PrintServiceStringsField__JOB_DONE_OTHER);
1593                     break;
1594             }
1595 
1596             (*env)->SetObjectField(env, callbackParams,
1597                     _JobCallbackParamsField__jobDoneResult, jStr);
1598         }
1599 
1600         int i, count;
1601         int max_value_reasons;
1602 
1603         if (print_job_failed) {
1604             max_value_reasons = IPP_JOB_STATE_REASON_MAX_VALUE;
1605         } else {
1606             max_value_reasons = PRINT_STATUS_MAX_STATE;
1607         }
1608 
1609         for (count = i = 0; i < max_value_reasons; i++) {
1610             if (cb_param->blocked_reasons & (1 << i)) {
1611                 count++;
1612             }
1613         }
1614 
1615         // Add any failed or block reasons to blocked_reasons
1616         if (count > 0) {
1617             jobjectArray stringArray;
1618             if (print_job_failed) {
1619                 stringArray = processFailReasons(env, cb_param->blocked_reasons, count);
1620             } else {
1621                 stringArray = processBlockStatus(env, cb_param->blocked_reasons, count);
1622             }
1623             (*env)->SetObjectField(env, callbackParams, _JobCallbackParamsField__blockedReasons,
1624                                    stringArray);
1625             (*env)->DeleteLocalRef(env, stringArray);
1626         }
1627 
1628         (*env)->SetIntField(env, callbackParams, _JobCallbackParamsField__jobId,
1629                 (jint) job_handle);
1630 
1631         if (cb_param->certificate) {
1632             LOGI("_wprint_callback_fn: copying certificate len=%d", cb_param->certificate_len);
1633             jbyteArray certificate = (*env)->NewByteArray(env, cb_param->certificate_len);
1634             jbyte *certificateBytes = (*env)->GetByteArrayElements(env, certificate, 0);
1635             memcpy(certificateBytes, (const void *) cb_param->certificate,
1636                 cb_param->certificate_len);
1637             (*env)->ReleaseByteArrayElements(env, certificate, certificateBytes, 0);
1638             (*env)->SetObjectField(env, callbackParams, _JobCallbackParamsField__certificate,
1639                 certificate);
1640             (*env)->DeleteLocalRef(env, certificate);
1641         } else {
1642             LOGI("_wprint_callback_fn: there is no certificate");
1643             // No cert, set NULL
1644             (*env)->SetObjectField(env, callbackParams, _JobCallbackParamsField__certificate,
1645                 NULL);
1646         }
1647 
1648         (*env)->CallVoidMethod(env, _callbackReceiver, _JobCallbackMethod__jobCallback,
1649                 (jint) job_handle, callbackParams);
1650         (*env)->DeleteLocalRef(env, callbackParams);
1651     }
1652 
1653     if (needDetach) {
1654         (*_JVM)->DetachCurrentThread(_JVM);
1655     }
1656 }
1657 
1658 /*
1659  * Initialize wprint JNI
1660  */
Java_com_android_bips_ipp_Backend_nativeInit(JNIEnv * env,jobject obj,jobject callbackReceiver,jstring fakeDir,jint apiVersion)1661 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeInit(
1662         JNIEnv *env, jobject obj, jobject callbackReceiver, jstring fakeDir,
1663         jint apiVersion) {
1664     LOGI("nativeInit JNIenv is %p", env);
1665     int result;
1666 
1667     // Setup the global JavaVM reference first.
1668     (*env)->GetJavaVM(env, &_JVM);
1669 
1670     // Initialize the Android API version value
1671     g_API_version = apiVersion;
1672 
1673     _initJNI(env, callbackReceiver, fakeDir);
1674 
1675     // initialize wprint library
1676     result = wprintInit();
1677 
1678     // return the result
1679     return result;
1680 }
1681 
1682 /*
1683  * Copies a given string and returns the copy
1684  */
copyToNewString(JNIEnv * env,jstring source)1685 static char *copyToNewString(JNIEnv *env, jstring source) {
1686     const char *fromJava;
1687     char *newString;
1688 
1689     fromJava = (*env)->GetStringUTFChars(env, source, NULL);
1690     if (fromJava == NULL) return NULL;
1691 
1692     newString = (char *) malloc(strlen(fromJava) + 1);
1693     strcpy(newString, fromJava);
1694     (*env)->ReleaseStringUTFChars(env, source, fromJava);
1695 
1696     return newString;
1697 }
1698 
1699 /*
1700  * JNI call to wprint to get capabilities. Returns caps converted to java.
1701  */
Java_com_android_bips_ipp_Backend_nativeGetCapabilities(JNIEnv * env,jobject obj,jstring address,jint port,jstring httpResource,jstring uriScheme,jlong timeout,jobject printerCaps)1702 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeGetCapabilities(
1703         JNIEnv *env, jobject obj, jstring address, jint port, jstring httpResource,
1704         jstring uriScheme, jlong timeout, jobject printerCaps) {
1705     jint result;
1706     printer_capabilities_t caps;
1707     wprint_connect_info_t connect_info;
1708 
1709     connect_info.printer_addr = copyToNewString(env, address);
1710     connect_info.uri_path = copyToNewString(env, httpResource);
1711     connect_info.uri_scheme = copyToNewString(env, uriScheme);
1712     connect_info.port_num = port;
1713     connect_info.timeout = timeout;
1714     connect_info.validate_certificate = NULL;
1715 
1716     LOGI("nativeGetCapabilities for %s JNIenv is %p", connect_info.printer_addr, env);
1717 
1718     // This call may take a while, and the JNI may be torn down when we return
1719     result = wprintGetCapabilities(&connect_info, &caps);
1720 
1721     if (connect_info.printer_addr) free((char *) connect_info.printer_addr);
1722     if (connect_info.uri_path) free((char *) connect_info.uri_path);
1723     if (connect_info.uri_scheme) free((char *) connect_info.uri_scheme);
1724 
1725     if (!wprintIsRunning() && result == 0) {
1726         result = ERROR;
1727     }
1728 
1729     // additional IPP checks
1730     if (result == 0) {
1731         if (caps.isSupported && (caps.ippVersionMajor < 1)) {
1732             caps.isSupported = 0;
1733         }
1734         _convertPrinterCaps_to_Java(env, printerCaps, &caps);
1735     }
1736 
1737     return result;
1738 }
1739 
1740 /*
1741  * JNI call to wprint to get default job params. Returns job params converted to java.
1742  */
Java_com_android_bips_ipp_Backend_nativeGetDefaultJobParameters(JNIEnv * env,jobject obj,jobject jobParams)1743 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeGetDefaultJobParameters(
1744         JNIEnv *env, jobject obj, jobject jobParams) {
1745     LOGI("nativeGetDefaultJobParameters, JNIenv is %p", env);
1746     jint result;
1747     wprint_job_params_t params;
1748 
1749     result = wprintGetDefaultJobParams(&params);
1750 
1751     _covertJobParams_to_Java(env, jobParams, &params);
1752     return result;
1753 }
1754 
1755 /*
1756  * JNI call to wprint to get final job params. Returns final params converted to java.
1757  */
Java_com_android_bips_ipp_Backend_nativeGetFinalJobParameters(JNIEnv * env,jobject obj,jobject jobParams,jobject printerCaps)1758 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeGetFinalJobParameters(
1759         JNIEnv *env, jobject obj, jobject jobParams, jobject printerCaps) {
1760     LOGI("nativeGetFinalJobParameters, JNIenv is %p", env);
1761     jint result;
1762     wprint_job_params_t params;
1763     printer_capabilities_t caps;
1764 
1765     _convertJobParams_to_C(env, jobParams, &params);
1766     _convertPrinterCaps_to_C(env, printerCaps, &caps);
1767 
1768     LOGD("nativeGetFinalJobParameters: After _convertJobParams_to_C: res=%d, name=%s",
1769             params.pdf_render_resolution, params.job_name);
1770     result = wprintGetFinalJobParams(&params, &caps);
1771 
1772     _covertJobParams_to_Java(env, jobParams, &params);
1773     return result;
1774 }
1775 
1776 /*
1777  * Convert certificate (if present) from printer capabilities into job_params.
1778  */
_convertCertificate(JNIEnv * env,jobject printerCaps,wprint_job_params_t * params)1779 static void _convertCertificate(JNIEnv *env, jobject printerCaps, wprint_job_params_t *params) {
1780     params->certificate = NULL;
1781     jbyteArray certificate = (jbyteArray) (*env)->GetObjectField(env, printerCaps,
1782             _LocalPrinterCapabilitiesField__certificate);
1783     if (certificate) {
1784         params->certificate_len = (*env)->GetArrayLength(env, certificate);
1785         params->certificate = malloc(params->certificate_len);
1786         if (params->certificate) {
1787             jbyte *certificateBytes = (*env)->GetByteArrayElements(env, certificate, NULL);
1788             memcpy(params->certificate, certificateBytes, params->certificate_len);
1789             (*env)->ReleaseByteArrayElements(env, certificate, certificateBytes, JNI_ABORT);
1790         }
1791     }
1792 }
1793 
1794 /*
1795  * JNI call to wprint to start a print job. Takes connection params, job params, caps, and file
1796  * array to complete the job
1797  */
Java_com_android_bips_ipp_Backend_nativeStartJob(JNIEnv * env,jobject obj,jstring address,jint port,jstring mimeType,jobject jobParams,jobject printerCaps,jobject fileArray,jstring jobDebugDir,jstring scheme)1798 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeStartJob(
1799         JNIEnv *env, jobject obj, jstring address, jint port, jstring mimeType, jobject jobParams,
1800         jobject printerCaps, jobject fileArray, jstring jobDebugDir, jstring scheme) {
1801     LOGI("nativeStartJob, JNIenv is %p", env);
1802     jint result = ERROR;
1803     wJob_t job_handle = ERROR;
1804     bool hasFiles = false;
1805 
1806     wprint_job_params_t params;
1807     printer_capabilities_t caps;
1808 
1809     _convertJobParams_to_C(env, jobParams, &params);
1810     _convertPrinterCaps_to_C(env, printerCaps, &caps);
1811     _convertCertificate(env, printerCaps, &params);
1812 
1813     LOGD("nativeStartJob: After _convertJobParams_to_C: res=%d, name=%s",
1814             params.pdf_render_resolution, params.job_name);
1815 
1816     const char *addressStr = (*env)->GetStringUTFChars(env, address, NULL);
1817     const char *mimeTypeStr = (*env)->GetStringUTFChars(env, mimeType, NULL);
1818     const char *dataDirStr = (*env)->GetStringUTFChars(env, _fakeDir, NULL);
1819     const char *schemeStr = (*env)->GetStringUTFChars(env, scheme, NULL);
1820 
1821     jsize len = 0;
1822     jobjectArray array;
1823 
1824     if (fileArray) {
1825         array = (jobjectArray) fileArray;
1826         len = (*env)->GetArrayLength(env, array);
1827         hasFiles = (len > 0);
1828     }
1829 
1830     int index = 0, pageIndex, incrementor;
1831     int page_range_arr[len];
1832 
1833     // Initialize page_range_arr (address defect reported by Coverity scans)
1834     memset((char *) page_range_arr, 0, sizeof(int) * len);
1835 
1836     int pdf_pages_ary[len];
1837     int pages_ary[len][MAX_NUM_PAGES];
1838     const char *print_format = _get_print_format(mimeTypeStr, &params, &caps);
1839 
1840     if (hasFiles) {
1841         result = OK;
1842         for (pageIndex = 0; ((result == OK) && (pageIndex < len)); pageIndex++) {
1843             jstring page = (jstring) (*env)->GetObjectArrayElement(env, array, pageIndex);
1844             const char *pageStr = (*env)->GetStringUTFChars(env, page, NULL);
1845             if (pageStr == NULL) {
1846                 result = ERROR;
1847             } else {
1848                 int page_count = 0;
1849                 if (_get_pdf_page_count(mimeTypeStr, &page_count, pageStr)) {
1850                     pdf_pages_ary[pageIndex] = page_count;
1851                     page_range_arr[pageIndex] = 0;
1852                     char page_range_str[MAX_NUM_PAGES];
1853                     memset(page_range_str, 0, MAX_NUM_PAGES);
1854                     _get_pdf_page_range(env, jobParams, &pages_ary[pageIndex][0],
1855                             pdf_pages_ary[pageIndex], &page_range_arr[pageIndex], page_range_str);
1856                 }
1857             }
1858             (*env)->ReleaseStringUTFChars(env, page, pageStr);
1859         }
1860 
1861         jstring page = (jstring) (*env)->GetObjectArrayElement(env, array, index);
1862         const char *pageStr = (*env)->GetStringUTFChars(env, page, NULL);
1863         if (pageStr == NULL) {
1864             result = ERROR;
1865         }
1866 
1867         if (len == 1) {
1868             if (_is_pdf_doc((char *) mimeTypeStr, (char *) pageStr)) {
1869                 if (page_range_arr[0] == 1) {
1870                     LOGI("smart duplex, disabling duplex");
1871                     params.duplex = DUPLEX_MODE_NONE;
1872                 }
1873             } else {
1874                 LOGI("smart duplex, disabling duplex");
1875                 params.duplex = DUPLEX_MODE_NONE;
1876             }
1877         }
1878 
1879         (*env)->ReleaseStringUTFChars(env, page, pageStr);
1880 
1881         bool shared_photo = (*env)->GetBooleanField(env, jobParams,
1882                                                     _LocalJobParamsField__shared_photo);
1883         bool preserve_scaling = (*env)->GetBooleanField(env, jobParams,
1884                                                         _LocalJobParamsField__preserve_scaling);
1885         LOGD("setting print-scaling job param");
1886         LOGD("shared_photo = %d", shared_photo);
1887         LOGD("preserve_scaling = %d", preserve_scaling);
1888 
1889         char print_scaling[MAX_PRINT_SCALING_LENGTH] = "";
1890         if (strcmp(print_format, PRINT_FORMAT_PDF) == 0) {
1891             LOGD("PDF pass-through");
1892             bool is_photo = strcasecmp(params.docCategory, "Photo") == 0;
1893             if ((is_photo && shared_photo) || preserve_scaling) {
1894                 for (int i = 0; i < caps.print_scalings_supported_count; i++) {
1895                     if (strcmp(caps.print_scalings_supported[i], "none") == 0) {
1896                         strlcpy(print_scaling, "none", sizeof(print_scaling));
1897                         break;
1898                     }
1899                 }
1900             } else {
1901                 bool auto_supported = false;
1902                 for (int i = 0; i < caps.print_scalings_supported_count; i++) {
1903                     if (strcmp(caps.print_scalings_supported[i], "auto") == 0) {
1904                         strlcpy(print_scaling, "auto", sizeof(print_scaling));
1905                         auto_supported = true;
1906                         break;
1907                     }
1908                 }
1909                 if (!auto_supported) {
1910                     if (strcmp(caps.print_scaling_default, "") != 0) {
1911                         strlcpy(print_scaling, caps.print_scaling_default,
1912                                 sizeof(caps.print_scaling_default));
1913                     } else {
1914                         strlcpy(print_scaling, "fit", sizeof(print_scaling));
1915                     }
1916                 }
1917             }
1918         }
1919         LOGD("setting print-scaling value = %s", print_scaling);
1920         strlcpy(params.print_scaling, print_scaling, sizeof(params.print_scaling));
1921 
1922         params.job_pages_per_set = 0;
1923         for (int i = 0; i < len; i++) {
1924             params.job_pages_per_set += pdf_pages_ary[i];
1925         }
1926 
1927         const char *jobDebugDirStr = NULL;
1928         if (jobDebugDir != NULL) {
1929             jobDebugDirStr = (*env)->GetStringUTFChars(env, jobDebugDir, NULL);
1930         }
1931         result = wprintStartJob(addressStr, port, &params, &caps, (char *) mimeTypeStr,
1932                 (char *) dataDirStr, _wprint_callback_fn, jobDebugDirStr, schemeStr);
1933         if (result == ERROR) {
1934             LOGE("failed to start job: error code :%d", errno);
1935         }
1936         if ((jobDebugDir != NULL) && (jobDebugDirStr != NULL)) {
1937             (*env)->ReleaseStringUTFChars(env, jobDebugDir, jobDebugDirStr);
1938         }
1939     } else {
1940         LOGE("empty file list");
1941     }
1942     if (result != ERROR) {
1943         job_handle = (wJob_t) result;
1944 
1945         // register job handle with service
1946         if (caps.faceDownTray) {
1947             index = 0;
1948             incrementor = 1;
1949         } else {
1950             index = len - 1;
1951             incrementor = -1;
1952         }
1953 
1954         result = OK;
1955         for (pageIndex = 1; ((result == OK) && (pageIndex <= len)); pageIndex++) {
1956             jstring page = (jstring) (*env)->GetObjectArrayElement(env, array, index);
1957             const char *pageStr = (*env)->GetStringUTFChars(env, page, NULL);
1958             if (pageStr == NULL) {
1959                 result = ERROR;
1960             } else {
1961                 if (_is_pdf_doc((char *) mimeTypeStr, (char *) pageStr)) {
1962                     result = _print_pdf_pages(job_handle, &caps, params.duplex, (char *) pageStr,
1963                             page_range_arr[index], pages_ary[index]);
1964                 } else {
1965                     result = wprintPage(job_handle, pageIndex, (char *) pageStr, false, false,
1966                             0, 0, 0, 0);
1967                 }
1968             }
1969             (*env)->ReleaseStringUTFChars(env, page, pageStr);
1970             index += incrementor;
1971         }
1972 
1973         wprintPage(job_handle, pageIndex, NULL, true, false, 0, 0, 0, 0);
1974         if (result != OK) {
1975             LOGE("failed to add some pages, aborting job");
1976             wprintCancelJob(job_handle);
1977             wprintEndJob(job_handle);
1978             job_handle = ERROR;
1979         }
1980     }
1981 
1982     if (params.certificate) {
1983         free(params.certificate);
1984     }
1985     (*env)->ReleaseStringUTFChars(env, mimeType, mimeTypeStr);
1986     (*env)->ReleaseStringUTFChars(env, address, addressStr);
1987     (*env)->ReleaseStringUTFChars(env, _fakeDir, dataDirStr);
1988     (*env)->ReleaseStringUTFChars(env, scheme, schemeStr);
1989     return job_handle;
1990 }
1991 
1992 /*
1993  * JNI call to wprint to end a print job
1994  */
Java_com_android_bips_ipp_Backend_nativeEndJob(JNIEnv * env,jobject obj,jint job_handle)1995 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeEndJob(
1996         JNIEnv *env, jobject obj, jint job_handle) {
1997     LOGI("nativeEndJob, JNIenv is %p", env);
1998     return wprintEndJob((wJob_t) job_handle);
1999 }
2000 
2001 /*
2002  * JNI call to wprint to cancel a print job
2003  */
Java_com_android_bips_ipp_Backend_nativeCancelJob(JNIEnv * env,jobject obj,jint job_handle)2004 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeCancelJob(
2005         JNIEnv *env, jobject obj, jint job_handle) {
2006     LOGI("nativeCancelJob, JNIenv is %p", env);
2007     return wprintCancelJob((wJob_t) job_handle);
2008 }
2009 
2010 /*
2011  * JNI call to wprint to exit
2012  */
Java_com_android_bips_ipp_Backend_nativeExit(JNIEnv * env,jobject obj)2013 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeExit(JNIEnv *env, jobject obj) {
2014     LOGI("nativeExit, JNIenv is %p", env);
2015 
2016     if (_LocalJobParamsClass) {
2017         (*env)->DeleteGlobalRef(env, _LocalJobParamsClass);
2018     }
2019     if (_LocalPrinterCapabilitiesClass) {
2020         (*env)->DeleteGlobalRef(env, _LocalPrinterCapabilitiesClass);
2021     }
2022     if (_JobCallbackParamsClass) {
2023         (*env)->DeleteGlobalRef(env, _JobCallbackParamsClass);
2024     }
2025     if (_callbackReceiver) {
2026         (*env)->DeleteGlobalRef(env, _callbackReceiver);
2027     }
2028     if (_JobCallbackClass) {
2029         (*env)->DeleteGlobalRef(env, _JobCallbackClass);
2030     }
2031     if (_fakeDir) {
2032         (*env)->DeleteGlobalRef(env, _fakeDir);
2033     }
2034     if (_PrintServiceStringsClass) {
2035         (*env)->DeleteGlobalRef(env, _PrintServiceStringsClass);
2036     }
2037 
2038     pdf_render_deinit(env);
2039     return wprintExit();
2040 }
2041 
2042 /*
2043  * Sets app name/version and os name
2044  */
Java_com_android_bips_ipp_Backend_nativeSetSourceInfo(JNIEnv * env,jobject obj,jstring appName,jstring appVersion,jstring osName)2045 JNIEXPORT void JNICALL Java_com_android_bips_ipp_Backend_nativeSetSourceInfo(
2046         JNIEnv *env, jobject obj, jstring appName, jstring appVersion, jstring osName) {
2047     LOGI("nativeSetSourceInfo, JNIenv is %p", env);
2048     const char *appNameStr = (*env)->GetStringUTFChars(env, appName, NULL);
2049     const char *appVersionStr = (*env)->GetStringUTFChars(env, appVersion, NULL);
2050     const char *osNameStr = (*env)->GetStringUTFChars(env, osName, NULL);
2051     wprintSetSourceInfo(appNameStr, appVersionStr, osNameStr);
2052     (*env)->ReleaseStringUTFChars(env, appName, appNameStr);
2053     (*env)->ReleaseStringUTFChars(env, appVersion, appVersionStr);
2054     (*env)->ReleaseStringUTFChars(env, osName, osNameStr);
2055 }