• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "../plugins/wprint_mupdf.h"
24 
25 #define TAG "wprintJNI"
26 
27 #define MAX_NUM_PAGES 2000
28 
29 static jclass _LocalJobParamsClass;
30 static jfieldID _LocalJobParamsField__borderless;
31 static jfieldID _LocalJobParamsField__duplex;
32 static jfieldID _LocalJobParamsField__media_size;
33 static jfieldID _LocalJobParamsField__media_type;
34 static jfieldID _LocalJobParamsField__media_tray;
35 static jfieldID _LocalJobParamsField__color_space;
36 static jfieldID _LocalJobParamsField__render_flags;
37 static jfieldID _LocalJobParamsField__num_copies;
38 static jfieldID _LocalJobParamsField__page_range;
39 static jfieldID _LocalJobParamsField__print_resolution;
40 static jfieldID _LocalJobParamsField__printable_width;
41 static jfieldID _LocalJobParamsField__printable_height;
42 static jfieldID _LocalJobParamsField__page_width;
43 static jfieldID _LocalJobParamsField__page_height;
44 static jfieldID _LocalJobParamsField__page_margin_top;
45 static jfieldID _LocalJobParamsField__page_margin_left;
46 static jfieldID _LocalJobParamsField__page_margin_right;
47 static jfieldID _LocalJobParamsField__page_margin_bottom;
48 static jfieldID _LocalJobParamsField__job_margin_top;
49 static jfieldID _LocalJobParamsField__job_margin_left;
50 static jfieldID _LocalJobParamsField__job_margin_right;
51 static jfieldID _LocalJobParamsField__job_margin_bottom;
52 static jfieldID _LocalJobParamsField__fit_to_page;
53 static jfieldID _LocalJobParamsField__fill_page;
54 static jfieldID _LocalJobParamsField__auto_rotate;
55 static jfieldID _LocalJobParamsField__portrait_mode;
56 static jfieldID _LocalJobParamsField__landscape_mode;
57 static jfieldID _LocalJobParamsField__nativeData;
58 static jfieldID _LocalJobParamsField__document_category;
59 static jfieldID _LocalJobParamsField__alignment;
60 static jfieldID _LocalJobParamsField__document_scaling;
61 static jfieldID _LocalJobParamsField__job_name;
62 static jfieldID _LocalJobParamsField__job_originating_user_name;
63 static jfieldID _LocalJobParamsField__pdf_render_resolution;
64 
65 static jclass _LocalPrinterCapabilitiesClass;
66 static jfieldID _LocalPrinterCapabilitiesField__name;
67 static jfieldID _LocalPrinterCapabilitiesField__path;
68 static jfieldID _LocalPrinterCapabilitiesField__uuid;
69 static jfieldID _LocalPrinterCapabilitiesField__location;
70 static jfieldID _LocalPrinterCapabilitiesField__duplex;
71 static jfieldID _LocalPrinterCapabilitiesField__borderless;
72 static jfieldID _LocalPrinterCapabilitiesField__color;
73 static jfieldID _LocalPrinterCapabilitiesField__isSupported;
74 static jfieldID _LocalPrinterCapabilitiesField__mediaDefault;
75 static jfieldID _LocalPrinterCapabilitiesField__supportedMediaTypes;
76 static jfieldID _LocalPrinterCapabilitiesField__supportedMediaSizes;
77 static jfieldID _LocalPrinterCapabilitiesField__nativeData;
78 
79 static jclass _JobCallbackClass;
80 static jobject _callbackReceiver;
81 static jmethodID _JobCallbackMethod__jobCallback;
82 
83 static jclass _JobCallbackParamsClass;
84 static jmethodID _JobCallbackParamsMethod__init;
85 static jfieldID _JobCallbackParamsField__jobId;
86 static jfieldID _JobCallbackParamsField__jobState;
87 static jfieldID _JobCallbackParamsField__jobDoneResult;
88 static jfieldID _JobCallbackParamsField__blockedReasons;
89 
90 static jclass _PrintServiceStringsClass;
91 static jfieldID _PrintServiceStringsField__JOB_STATE_QUEUED;
92 static jfieldID _PrintServiceStringsField__JOB_STATE_RUNNING;
93 static jfieldID _PrintServiceStringsField__JOB_STATE_BLOCKED;
94 static jfieldID _PrintServiceStringsField__JOB_STATE_DONE;
95 static jfieldID _PrintServiceStringsField__JOB_STATE_OTHER;
96 static jfieldID _PrintServiceStringsField__JOB_DONE_OK;
97 static jfieldID _PrintServiceStringsField__JOB_DONE_ERROR;
98 static jfieldID _PrintServiceStringsField__JOB_DONE_CANCELLED;
99 static jfieldID _PrintServiceStringsField__JOB_DONE_CORRUPT;
100 static jfieldID _PrintServiceStringsField__JOB_DONE_OTHER;
101 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OFFLINE;
102 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__BUSY;
103 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__CANCELLED;
104 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_PAPER;
105 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_INK;
106 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_TONER;
107 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__JAMMED;
108 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__DOOR_OPEN;
109 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__SERVICE_REQUEST;
110 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_INK;
111 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_TONER;
112 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__REALLY_LOW_ON_INK;
113 static jfieldID _PrintServiceStringsField__BLOCKED_REASON__UNKNOWN;
114 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER;
115 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL;
116 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER_VERTICAL;
117 static jfieldID _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL_ON_ORIENTATION;
118 
119 // Global so it can be used in PDF render code
120 JavaVM *_JVM = NULL;
121 
122 static jstring _fakeDir;
123 
124 int g_API_version = 0;
125 
126 /*
127  * Convert char * to a java object
128  */
129 static void stringToJava(JNIEnv *env, jobject obj, jfieldID id, const char *str);
130 
131 /*
132  * Retuns if the mime type is MIME_TYPE_PDF
133  */
_is_pdf_doc(const char * mime_type,const char * pathname)134 static bool _is_pdf_doc(const char *mime_type, const char *pathname) {
135     if (mime_type == NULL || pathname == NULL) {
136         return false;
137     }
138 
139     if (strcmp(mime_type, MIME_TYPE_PDF) == 0) {
140         return true;
141     }
142 
143     return false;
144 }
145 
146 /*
147  * Returns if the string is numeric
148  */
_isNumeric(const char * s)149 static int _isNumeric(const char *s) {
150     if (s == NULL || *s == '\0' || isspace(*s)) {
151         return 0;
152     }
153     char *p;
154     strtod(s, &p);
155     return *p == '\0';
156 }
157 
158 /*
159  * Outputs the number of pages in a pdf to page_count. Returns False if an error ocurred
160  */
_get_pdf_page_count(const char * mime_type,int * page_count,const char * pathname)161 static bool _get_pdf_page_count(const char *mime_type, int *page_count, const char *pathname) {
162     *page_count = 0;
163 
164     if (!_is_pdf_doc(mime_type, pathname)) {
165         return false;
166     }
167 
168     pdf_render_ifc_t *pdf_render_ifc = create_pdf_render_ifc();
169     *page_count = pdf_render_ifc->openDocument(pdf_render_ifc, pathname);
170     pdf_render_ifc->destroy(pdf_render_ifc);
171 
172     LOGI("pdf page count for %s: %d", pathname, *page_count);
173     if (*page_count < 0) {
174         LOGE("page count error");
175         *page_count = 0;
176     }
177     return true;
178 }
179 
180 /*
181  * Reorders pdf pages before sending to the printer. In general the last page is printed first.
182  * Removes pages from pages_ary if they are not in the specified range.
183  */
_order_pdf_pages(int num_pages,int * pages_ary,int * num_index,char * page_range_split)184 static bool _order_pdf_pages(int num_pages, int *pages_ary, int *num_index,
185         char *page_range_split) {
186     bool succeeded = false;
187     char num_begin_ary[5] = "";
188     char num_end_ary[5] = "";
189     int num_counter = 0;
190     bool dash_encountered = false;
191     int range_count = 0;
192 
193     // initialize to 0
194     memset(num_begin_ary, 0, 5);
195     memset(num_end_ary, 0, 5);
196 
197     for (range_count = 0; range_count < (int) strlen(page_range_split); range_count++) {
198         // skip spaces
199         if (!isspace(page_range_split[range_count])) {
200             // store first number found in range in num_begin_ary
201             // and second number (after the dash '-') in num_end_ary
202             // skip the dash ('-') character
203             if (page_range_split[range_count] == '-') {
204                 dash_encountered = true;
205                 num_counter = 0;
206                 continue;
207             }
208 
209             if (!dash_encountered) {
210                 num_begin_ary[num_counter++] = page_range_split[range_count];
211             } else {
212                 num_end_ary[num_counter++] = page_range_split[range_count];
213             }
214         }
215     }
216 
217     // fill in first cell of end num with 0 so array has a valid number
218     if (!dash_encountered) {
219         num_end_ary[0] = '0';
220     }
221 
222     // make sure numeric values are stored in num_begin_ary and num_end_ary
223     if (_isNumeric(num_begin_ary) && _isNumeric(num_end_ary)) {
224         // convert to integers
225         int num_begin = atoi(num_begin_ary);
226         int num_end = atoi(num_end_ary);
227 
228         // if ending number was 0, there was no range, only a single page number
229         // so, set it to the value of the beginning number
230         if (num_end == 0) {
231             num_end = num_begin;
232         }
233 
234         // make sure beginning and ending numbers are at least 1
235         if (num_begin > 0 && num_end > 0) {
236             // make sure the beginning and ending numbers are not greater than the page count
237             if (num_begin <= num_pages && num_end <= num_pages) {
238                 if (num_end >= num_begin) {
239                     // make sure the upper bound does not exceed the number of pages
240                     if (num_end > num_pages) {
241                         num_end = num_pages;
242                     }
243                     // store range in pages_ary in ascending order
244                     int count = 0;
245                     for (count = *num_index; count <= (*num_index + num_end - num_begin); count++) {
246                         *(pages_ary + count) = num_begin++;
247                         *num_index += 1;
248                     }
249                 } else {
250                     // reverse order
251                     // make sure the upper bound does not exceed the number of pages
252                     if (num_begin > num_pages) {
253                         num_begin = num_pages;
254                     }
255                     // store range in pages_ary in descending order
256                     int count = 0;
257                     for (count = *num_index; count <= *num_index + num_begin - num_end; count++) {
258                         *(pages_ary + count) = num_begin--;
259                         *num_index += 1;
260                     }
261                 }
262                 succeeded = true;
263             } else {
264                 LOGE("_order_pdf_pages(), ERROR: first and/or last numbers are not greater than "
265                         "%d: first num=%d, second num=%d", num_pages, num_begin, num_end);
266             }
267         } else {
268             LOGE("_order_pdf_pages(), ERROR: first and/or last numbers are not greater than 0: "
269                     "first num=%d, second num=%d", num_begin, num_end);
270         }
271     } else {
272         LOGE("_order_pdf_pages(), ERROR: first and/or last numbers are not numeric: first num=%s, "
273                 "second num=%s", num_begin_ary, num_end_ary);
274     }
275     return succeeded;
276 }
277 
278 /*
279  * Outputs page range of a pdf to page_range_str
280  */
_get_pdf_page_range(JNIEnv * env,jobject javaJobParams,int * pages_ary,int num_pages,int * num_index,char * page_range_str)281 static void _get_pdf_page_range(JNIEnv *env, jobject javaJobParams, int *pages_ary, int num_pages,
282         int *num_index, char *page_range_str) {
283     char *page_range = NULL;
284     jstring pageRangeObject = (jstring) (*env)->GetObjectField(env, javaJobParams,
285             _LocalJobParamsField__page_range);
286     if (pageRangeObject) {
287         int page_range_size = (*env)->GetStringLength(env, pageRangeObject);
288         const jbyte *pageRange = (jbyte *) (*env)->GetStringUTFChars(env, pageRangeObject, 0);
289         if (strcmp((char *) pageRange, "") != 0) {
290             page_range = (char *) malloc(page_range_size + 1);
291             memset(page_range, 0, page_range_size + 1);
292             strncpy(page_range, (char *) pageRange, page_range_size);
293 
294             // no empty strings
295             if (strcmp(page_range, "") == 0) {
296                 free(page_range);
297                 page_range = NULL;
298             }
299 
300             (*env)->ReleaseStringUTFChars(env, pageRangeObject, (const char *) pageRange);
301             LOGD("_get_pdf_page_range(), page_range from JNI environment=%s", page_range);
302         }
303     }
304 
305     if (!page_range) {
306         page_range = (char *) malloc(MAX_NUM_PAGES + 1);
307         memset(page_range, 0, MAX_NUM_PAGES + 1);
308 
309         snprintf(page_range_str, MAX_NUM_PAGES, "1-%d", num_pages);
310         snprintf(page_range, MAX_NUM_PAGES, "1-%d", num_pages);
311     } else {
312         strncpy(page_range_str, page_range, MAX_NUM_PAGES);
313     }
314 
315     LOGD("_get_pdf_page_range(), range: %s, pages in document: %d", page_range_str, num_pages);
316 
317     // get the first token in page_range_str
318     memset(pages_ary, 0, MAX_NUM_PAGES);
319     char *page_range_split = strtok(page_range, ",");
320     while (page_range_split != NULL) {
321         if (!_order_pdf_pages(num_pages, pages_ary, num_index, page_range_split)) {
322             snprintf(page_range_str, MAX_NUM_PAGES, "1-%d", num_pages);
323             LOGD("_get_pdf_page_range(), setting page_range to: %s", page_range_str);
324             _order_pdf_pages(num_pages, pages_ary, num_index, page_range_str);
325             break;
326         }
327 
328         // get next range token
329         page_range_split = strtok(NULL, ",");
330     }
331 
332     if (page_range) {
333         free(page_range);
334     }
335 }
336 
337 /*
338  * Sends a pdf to a printer
339  */
_print_pdf_pages(wJob_t job_handle,printer_capabilities_t * printer_cap,duplex_t duplex,char * pathname,int num_index,int * pages_ary)340 static jint _print_pdf_pages(wJob_t job_handle, printer_capabilities_t *printer_cap,
341         duplex_t duplex, char *pathname, int num_index, int *pages_ary) {
342     int num_pages = num_index;
343 
344     // now, print the pages
345     int page_index;
346     jint result = ERROR;
347 
348     // print forward direction if printer prints pages face down; otherwise print backward
349     // NOTE: last page is sent from calling function
350     if (printer_cap->faceDownTray || duplex) {
351         LOGD("_print_pdf_pages(), pages print face down or duplex, printing in normal order");
352         page_index = 0;
353         while (page_index < num_pages) {
354             LOGD("_print_pdf_pages(), PRINTING PDF: %d", *(pages_ary + page_index));
355             result = wprintPage(job_handle, *(pages_ary + page_index++), pathname, false, true,
356                     0, 0, 0, 0);
357 
358             if (result != OK) {
359                 break;
360             }
361         }
362     } else {
363         LOGI("   _print_pdf_pages(), pages print face up, printing in reverse");
364         page_index = num_pages - 1;
365         while (page_index >= 0) {
366             LOGD("_print_pdf_pages(), PRINTING PDF: %s, page: %d", pathname,
367                     *(pages_ary + page_index));
368             result = wprintPage(job_handle, *(pages_ary + page_index--), pathname, false, true,
369                     0, 0, 0, 0);
370             if (result != OK) {
371                 break;
372             }
373         }
374     }
375 
376     LOGI("   _print_pdf_pages(), printing result: %s", result == OK ? "OK" : "ERROR");
377     return result;
378 }
379 
380 /*
381  * Initialize JNI. Maps java values to jni values.
382  */
_initJNI(JNIEnv * env,jobject callbackReceiver,jstring fakeDir)383 static void _initJNI(JNIEnv *env, jobject callbackReceiver, jstring fakeDir) {
384     _fakeDir = (jstring) (*env)->NewGlobalRef(env, fakeDir);
385 
386     // fill out static accessors for wPrintJobParameters
387     _LocalJobParamsClass = (jclass) (*env)->NewGlobalRef(
388             env, (*env)->FindClass(env, "com/android/bips/jni/LocalJobParams"));
389     _LocalJobParamsField__borderless = (*env)->GetFieldID(env, _LocalJobParamsClass, "borderless",
390             "I");
391     _LocalJobParamsField__duplex = (*env)->GetFieldID(env, _LocalJobParamsClass, "duplex", "I");
392     _LocalJobParamsField__media_size = (*env)->GetFieldID(env, _LocalJobParamsClass, "media_size",
393             "I");
394     _LocalJobParamsField__media_type = (*env)->GetFieldID(env, _LocalJobParamsClass, "media_type",
395             "I");
396     _LocalJobParamsField__media_tray = (*env)->GetFieldID(env, _LocalJobParamsClass, "media_tray",
397             "I");
398     _LocalJobParamsField__color_space = (*env)->GetFieldID(env, _LocalJobParamsClass, "color_space",
399             "I");
400     _LocalJobParamsField__render_flags = (*env)->GetFieldID(env, _LocalJobParamsClass,
401             "render_flags", "I");
402     _LocalJobParamsField__num_copies = (*env)->GetFieldID(env, _LocalJobParamsClass, "num_copies",
403             "I");
404     _LocalJobParamsField__page_range = (*env)->GetFieldID(env, _LocalJobParamsClass, "page_range",
405             "Ljava/lang/String;");
406     _LocalJobParamsField__print_resolution = (*env)->GetFieldID(env, _LocalJobParamsClass,
407             "print_resolution", "I");
408     _LocalJobParamsField__printable_width = (*env)->GetFieldID(env, _LocalJobParamsClass,
409             "printable_width", "I");
410     _LocalJobParamsField__printable_height = (*env)->GetFieldID(env, _LocalJobParamsClass,
411             "printable_height", "I");
412     _LocalJobParamsField__page_width = (*env)->GetFieldID(env, _LocalJobParamsClass, "page_width",
413             "F");
414     _LocalJobParamsField__page_height = (*env)->GetFieldID(env, _LocalJobParamsClass, "page_height",
415             "F");
416     _LocalJobParamsField__page_margin_top = (*env)->GetFieldID(env, _LocalJobParamsClass,
417             "page_margin_top", "F");
418     _LocalJobParamsField__page_margin_left = (*env)->GetFieldID(env, _LocalJobParamsClass,
419             "page_margin_left", "F");
420     _LocalJobParamsField__page_margin_right = (*env)->GetFieldID(env, _LocalJobParamsClass,
421             "page_margin_right", "F");
422     _LocalJobParamsField__page_margin_bottom = (*env)->GetFieldID(env, _LocalJobParamsClass,
423             "page_margin_bottom", "F");
424     _LocalJobParamsField__nativeData = (*env)->GetFieldID(env, _LocalJobParamsClass, "nativeData",
425             "[B");
426     _LocalJobParamsField__fit_to_page = (*env)->GetFieldID(env, _LocalJobParamsClass, "fit_to_page",
427             "Z");
428     _LocalJobParamsField__fill_page = (*env)->GetFieldID(env, _LocalJobParamsClass, "fill_page",
429             "Z");
430     _LocalJobParamsField__auto_rotate = (*env)->GetFieldID(env, _LocalJobParamsClass, "auto_rotate",
431             "Z");
432     _LocalJobParamsField__portrait_mode = (*env)->GetFieldID(env, _LocalJobParamsClass,
433             "portrait_mode", "Z");
434     _LocalJobParamsField__landscape_mode = (*env)->GetFieldID(env, _LocalJobParamsClass,
435             "landscape_mode", "Z");
436     _LocalJobParamsField__document_category = (*env)->GetFieldID(env, _LocalJobParamsClass,
437             "document_category",
438             "Ljava/lang/String;");
439     _LocalJobParamsField__alignment = (*env)->GetFieldID(env, _LocalJobParamsClass, "alignment",
440             "I");
441     _LocalJobParamsField__job_margin_top = (*env)->GetFieldID(env, _LocalJobParamsClass,
442             "job_margin_top", "F");
443     _LocalJobParamsField__job_margin_left = (*env)->GetFieldID(env, _LocalJobParamsClass,
444             "job_margin_left", "F");
445     _LocalJobParamsField__job_margin_right = (*env)->GetFieldID(env, _LocalJobParamsClass,
446             "job_margin_right", "F");
447     _LocalJobParamsField__job_margin_bottom = (*env)->GetFieldID(env, _LocalJobParamsClass,
448             "job_margin_bottom", "F");
449     _LocalJobParamsField__document_scaling = (*env)->GetFieldID(env, _LocalJobParamsClass,
450             "document_scaling", "Z");
451     _LocalJobParamsField__job_name = (*env)->GetFieldID(env, _LocalJobParamsClass, "job_name",
452             "Ljava/lang/String;");
453     _LocalJobParamsField__job_originating_user_name = (*env)->GetFieldID(
454             env, _LocalJobParamsClass, "job_originating_user_name", "Ljava/lang/String;");
455     _LocalJobParamsField__pdf_render_resolution = (*env)->GetFieldID(env, _LocalJobParamsClass,
456             "pdf_render_resolution", "I");
457 
458     // fill out static accessors for LocalPrinterCapabilities
459     _LocalPrinterCapabilitiesClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(
460             env, "com/android/bips/jni/LocalPrinterCapabilities"));
461     _LocalPrinterCapabilitiesField__path = (*env)->GetFieldID(
462             env, _LocalPrinterCapabilitiesClass, "path", "Ljava/lang/String;");
463     _LocalPrinterCapabilitiesField__name = (*env)->GetFieldID(
464             env, _LocalPrinterCapabilitiesClass, "name", "Ljava/lang/String;");
465     _LocalPrinterCapabilitiesField__uuid = (*env)->GetFieldID(
466             env, _LocalPrinterCapabilitiesClass, "uuid", "Ljava/lang/String;");
467     _LocalPrinterCapabilitiesField__location = (*env)->GetFieldID(
468             env, _LocalPrinterCapabilitiesClass, "location", "Ljava/lang/String;");
469     _LocalPrinterCapabilitiesField__duplex = (*env)->GetFieldID(
470             env, _LocalPrinterCapabilitiesClass, "duplex", "Z");
471     _LocalPrinterCapabilitiesField__borderless = (*env)->GetFieldID(
472             env, _LocalPrinterCapabilitiesClass, "borderless", "Z");
473     _LocalPrinterCapabilitiesField__color = (*env)->GetFieldID(
474             env, _LocalPrinterCapabilitiesClass, "color", "Z");
475     _LocalPrinterCapabilitiesField__isSupported = (*env)->GetFieldID(
476             env, _LocalPrinterCapabilitiesClass, "isSupported", "Z");
477     _LocalPrinterCapabilitiesField__mediaDefault = (*env)->GetFieldID(
478             env, _LocalPrinterCapabilitiesClass, "mediaDefault", "Ljava/lang/String;");
479     _LocalPrinterCapabilitiesField__supportedMediaTypes = (*env)->GetFieldID(
480             env, _LocalPrinterCapabilitiesClass, "supportedMediaTypes", "[I");
481     _LocalPrinterCapabilitiesField__supportedMediaSizes = (*env)->GetFieldID(
482             env, _LocalPrinterCapabilitiesClass, "supportedMediaSizes", "[I");
483     _LocalPrinterCapabilitiesField__nativeData = (*env)->GetFieldID(
484             env, _LocalPrinterCapabilitiesClass, "nativeData", "[B");
485 
486     _JobCallbackParamsClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(
487             env, "com/android/bips/jni/JobCallbackParams"));
488     _JobCallbackParamsMethod__init = (*env)->GetMethodID(env, _JobCallbackParamsClass,
489             "<init>", "()V");
490     _JobCallbackParamsField__jobId = (*env)->GetFieldID(env, _JobCallbackParamsClass, "jobId",
491             "I");
492     _JobCallbackParamsField__jobState = (*env)->GetFieldID(
493             env, _JobCallbackParamsClass, "jobState", "Ljava/lang/String;");
494     _JobCallbackParamsField__jobDoneResult = (*env)->GetFieldID(
495             env, _JobCallbackParamsClass, "jobDoneResult", "Ljava/lang/String;");
496     _JobCallbackParamsField__blockedReasons = (*env)->GetFieldID(
497             env, _JobCallbackParamsClass, "blockedReasons", "[Ljava/lang/String;");
498 
499     if (callbackReceiver) {
500         _callbackReceiver = (jobject) (*env)->NewGlobalRef(env, callbackReceiver);
501     }
502     if (_callbackReceiver) {
503         _JobCallbackClass = (jclass) (*env)->NewGlobalRef(env, (*env)->GetObjectClass(
504                 env, _callbackReceiver));
505         _JobCallbackMethod__jobCallback = (*env)->GetMethodID(
506                 env, _JobCallbackClass, "jobCallback",
507                 "(ILcom/android/bips/jni/JobCallbackParams;)V");
508     } else {
509         _callbackReceiver = 0;
510     }
511 
512     _PrintServiceStringsClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(
513             env, "com/android/bips/jni/BackendConstants"));
514     _PrintServiceStringsField__JOB_STATE_QUEUED = (*env)->GetStaticFieldID(
515             env, _PrintServiceStringsClass, "JOB_STATE_QUEUED", "Ljava/lang/String;");
516     _PrintServiceStringsField__JOB_STATE_RUNNING = (*env)->GetStaticFieldID(
517             env, _PrintServiceStringsClass, "JOB_STATE_RUNNING", "Ljava/lang/String;");
518     _PrintServiceStringsField__JOB_STATE_BLOCKED = (*env)->GetStaticFieldID(
519             env, _PrintServiceStringsClass, "JOB_STATE_BLOCKED", "Ljava/lang/String;");
520     _PrintServiceStringsField__JOB_STATE_DONE = (*env)->GetStaticFieldID(
521             env, _PrintServiceStringsClass, "JOB_STATE_DONE", "Ljava/lang/String;");
522     _PrintServiceStringsField__JOB_STATE_OTHER = (*env)->GetStaticFieldID(
523             env, _PrintServiceStringsClass, "JOB_STATE_OTHER", "Ljava/lang/String;");
524     _PrintServiceStringsField__JOB_DONE_OK = (*env)->GetStaticFieldID(
525             env, _PrintServiceStringsClass, "JOB_DONE_OK", "Ljava/lang/String;");
526     _PrintServiceStringsField__JOB_DONE_ERROR = (*env)->GetStaticFieldID(
527             env, _PrintServiceStringsClass, "JOB_DONE_ERROR", "Ljava/lang/String;");
528     _PrintServiceStringsField__JOB_DONE_CANCELLED = (*env)->GetStaticFieldID(
529             env, _PrintServiceStringsClass, "JOB_DONE_CANCELLED", "Ljava/lang/String;");
530     _PrintServiceStringsField__JOB_DONE_CORRUPT = (*env)->GetStaticFieldID(
531             env, _PrintServiceStringsClass, "JOB_DONE_CORRUPT", "Ljava/lang/String;");
532     _PrintServiceStringsField__JOB_DONE_OTHER = (*env)->GetStaticFieldID(
533             env, _PrintServiceStringsClass, "JOB_DONE_OTHER", "Ljava/lang/String;");
534     _PrintServiceStringsField__BLOCKED_REASON__OFFLINE = (*env)->GetStaticFieldID(
535             env, _PrintServiceStringsClass, "BLOCKED_REASON__OFFLINE", "Ljava/lang/String;");
536     _PrintServiceStringsField__BLOCKED_REASON__BUSY = (*env)->GetStaticFieldID(
537             env, _PrintServiceStringsClass, "BLOCKED_REASON__BUSY", "Ljava/lang/String;");
538     _PrintServiceStringsField__BLOCKED_REASON__CANCELLED = (*env)->GetStaticFieldID(
539             env, _PrintServiceStringsClass, "BLOCKED_REASON__CANCELLED", "Ljava/lang/String;");
540     _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_PAPER = (*env)->GetStaticFieldID(
541             env, _PrintServiceStringsClass, "BLOCKED_REASON__OUT_OF_PAPER", "Ljava/lang/String;");
542     _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_INK = (*env)->GetStaticFieldID(
543             env, _PrintServiceStringsClass, "BLOCKED_REASON__OUT_OF_INK", "Ljava/lang/String;");
544     _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_TONER = (*env)->GetStaticFieldID(
545             env, _PrintServiceStringsClass, "BLOCKED_REASON__OUT_OF_TONER", "Ljava/lang/String;");
546     _PrintServiceStringsField__BLOCKED_REASON__JAMMED = (*env)->GetStaticFieldID(
547             env, _PrintServiceStringsClass, "BLOCKED_REASON__JAMMED", "Ljava/lang/String;");
548     _PrintServiceStringsField__BLOCKED_REASON__DOOR_OPEN = (*env)->GetStaticFieldID(
549             env, _PrintServiceStringsClass, "BLOCKED_REASON__DOOR_OPEN", "Ljava/lang/String;");
550     _PrintServiceStringsField__BLOCKED_REASON__SERVICE_REQUEST = (*env)->GetStaticFieldID(
551             env, _PrintServiceStringsClass, "BLOCKED_REASON__SERVICE_REQUEST",
552             "Ljava/lang/String;");
553     _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_INK = (*env)->GetStaticFieldID(
554             env, _PrintServiceStringsClass, "BLOCKED_REASON__LOW_ON_INK", "Ljava/lang/String;");
555     _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_TONER = (*env)->GetStaticFieldID(
556             env, _PrintServiceStringsClass, "BLOCKED_REASON__LOW_ON_TONER", "Ljava/lang/String;");
557     _PrintServiceStringsField__BLOCKED_REASON__REALLY_LOW_ON_INK = (*env)->GetStaticFieldID(
558             env, _PrintServiceStringsClass, "BLOCKED_REASON__REALLY_LOW_ON_INK",
559             "Ljava/lang/String;");
560     _PrintServiceStringsField__BLOCKED_REASON__UNKNOWN = (*env)->GetStaticFieldID(
561             env, _PrintServiceStringsClass, "BLOCKED_REASON__UNKNOWN", "Ljava/lang/String;");
562 
563     _PrintServiceStringsField__ALIGNMENT__CENTER = (*env)->GetStaticFieldID(
564             env, _PrintServiceStringsClass, "ALIGN_CENTER", "I");
565     _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL = (*env)->GetStaticFieldID(
566             env, _PrintServiceStringsClass, "ALIGN_CENTER_HORIZONTAL", "I");
567     _PrintServiceStringsField__ALIGNMENT__CENTER_VERTICAL = (*env)->GetStaticFieldID(
568             env, _PrintServiceStringsClass, "ALIGN_CENTER_VERTICIAL", "I");
569     _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL_ON_ORIENTATION =
570             (*env)->GetStaticFieldID(env, _PrintServiceStringsClass,
571                     "ALIGN_CENTER_HORIZONTAL_ON_ORIENTATION", "I");
572 
573     pdf_render_init(env);
574 }
575 
576 /*
577  * Converts java printer caps to c and saves them to wprintPrinterCaps
578  */
_convertPrinterCaps_to_C(JNIEnv * env,jobject javaPrinterCaps,printer_capabilities_t * wprintPrinterCaps)579 static int _convertPrinterCaps_to_C(JNIEnv *env, jobject javaPrinterCaps,
580         printer_capabilities_t *wprintPrinterCaps) {
581     if (!javaPrinterCaps || !wprintPrinterCaps) {
582         return ERROR;
583     }
584 
585     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
586             env, javaPrinterCaps, _LocalPrinterCapabilitiesField__nativeData);
587     if (!nativeDataObject) {
588         return ERROR;
589     }
590     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
591     memcpy(wprintPrinterCaps, (const void *) nativeDataPtr, sizeof(printer_capabilities_t));
592     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, JNI_ABORT);
593 
594     return OK;
595 }
596 
597 /*
598  * Converts printer caps to java and saves them to javaPrinterCaps
599  */
_convertPrinterCaps_to_Java(JNIEnv * env,jobject javaPrinterCaps,const printer_capabilities_t * wprintPrinterCaps)600 static int _convertPrinterCaps_to_Java(JNIEnv *env, jobject javaPrinterCaps,
601         const printer_capabilities_t *wprintPrinterCaps) {
602     if (!javaPrinterCaps || !wprintPrinterCaps) {
603         return ERROR;
604     }
605 
606     int arrayCreated = 0;
607     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
608             env, javaPrinterCaps, _LocalPrinterCapabilitiesField__nativeData);
609     if (!nativeDataObject) {
610         arrayCreated = 1;
611         nativeDataObject = (*env)->NewByteArray(env, sizeof(printer_capabilities_t));
612     }
613 
614     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
615     memcpy((void *) nativeDataPtr, wprintPrinterCaps, sizeof(printer_capabilities_t));
616     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, 0);
617 
618     if (arrayCreated) {
619         (*env)->SetObjectField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__nativeData,
620                 nativeDataObject);
621         (*env)->DeleteLocalRef(env, nativeDataObject);
622     }
623 
624     (*env)->SetBooleanField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__duplex,
625             (jboolean) wprintPrinterCaps->duplex);
626     (*env)->SetBooleanField(env, javaPrinterCaps,
627             _LocalPrinterCapabilitiesField__borderless,
628             (jboolean) wprintPrinterCaps->borderless);
629     (*env)->SetBooleanField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__color,
630             (jboolean) wprintPrinterCaps->color);
631     (*env)->SetBooleanField(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__isSupported,
632             (jboolean) wprintPrinterCaps->isSupported);
633 
634     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__mediaDefault,
635             wprintPrinterCaps->mediaDefault);
636     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__path,
637             wprintPrinterCaps->printerUri);
638     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__name,
639             wprintPrinterCaps->name);
640     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__uuid,
641             wprintPrinterCaps->uuid);
642     stringToJava(env, javaPrinterCaps, _LocalPrinterCapabilitiesField__location,
643             wprintPrinterCaps->location);
644 
645     jintArray intArray;
646     int *intArrayPtr;
647     int index;
648 
649     intArray = (*env)->NewIntArray(env, wprintPrinterCaps->numSupportedMediaTypes);
650     intArrayPtr = (*env)->GetIntArrayElements(env, intArray, NULL);
651     for (index = 0; index < wprintPrinterCaps->numSupportedMediaTypes; index++) {
652         intArrayPtr[index] = (int) wprintPrinterCaps->supportedMediaTypes[index];
653     }
654     (*env)->ReleaseIntArrayElements(env, intArray, intArrayPtr, 0);
655     (*env)->SetObjectField(env, javaPrinterCaps,
656             _LocalPrinterCapabilitiesField__supportedMediaTypes, intArray);
657     (*env)->DeleteLocalRef(env, intArray);
658 
659     intArray = (*env)->NewIntArray(env, wprintPrinterCaps->numSupportedMediaSizes);
660     intArrayPtr = (*env)->GetIntArrayElements(env, intArray, NULL);
661     for (index = 0; index < wprintPrinterCaps->numSupportedMediaSizes; index++) {
662         intArrayPtr[index] = (int) wprintPrinterCaps->supportedMediaSizes[index];
663     }
664     (*env)->ReleaseIntArrayElements(env, intArray, intArrayPtr, 0);
665     (*env)->SetObjectField(env, javaPrinterCaps,
666             _LocalPrinterCapabilitiesField__supportedMediaSizes, intArray);
667     (*env)->DeleteLocalRef(env, intArray);
668 
669     int count;
670     for (count = index = 0; index < (sizeof(int) * 8); index++) {
671         if ((wprintPrinterCaps->supportedInputMimeTypes & (1 << index)) != 0) {
672             count++;
673         }
674     }
675 
676     return OK;
677 }
678 
679 /*
680  * Converts str to a java string
681  */
stringToJava(JNIEnv * env,jobject obj,jfieldID id,const char * str)682 static void stringToJava(JNIEnv *env, jobject obj, jfieldID id, const char *str) {
683     jstring jStr;
684 
685     // If null, copy an empty string
686     if (!str) str = "";
687 
688     jStr = (*env)->NewStringUTF(env, str);
689     (*env)->SetObjectField(env, obj, id, jStr);
690     (*env)->DeleteLocalRef(env, jStr);
691 }
692 
693 /*
694  * Converts javaJobParams to C and saves them to wprintJobParams
695  */
_convertJobParams_to_C(JNIEnv * env,jobject javaJobParams,wprint_job_params_t * wprintJobParams)696 static int _convertJobParams_to_C(JNIEnv *env, jobject javaJobParams,
697         wprint_job_params_t *wprintJobParams) {
698     if (!javaJobParams || !wprintJobParams) {
699         return ERROR;
700     }
701 
702     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
703             env, javaJobParams, _LocalJobParamsField__nativeData);
704     if (nativeDataObject == 0) {
705         return ERROR;
706     }
707 
708     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
709     memcpy(wprintJobParams, (const void *) nativeDataPtr, sizeof(wprint_job_params_t));
710     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, JNI_ABORT);
711 
712     wprintJobParams->media_size = (media_size_t) (*env)->GetIntField(
713             env, javaJobParams, _LocalJobParamsField__media_size);
714     wprintJobParams->media_type = (media_type_t) (*env)->GetIntField(
715             env, javaJobParams, _LocalJobParamsField__media_type);
716     wprintJobParams->duplex = (duplex_t) (*env)->GetIntField(
717             env, javaJobParams, _LocalJobParamsField__duplex);
718     wprintJobParams->color_space = (color_space_t) (*env)->GetIntField(
719             env, javaJobParams, _LocalJobParamsField__color_space);
720     wprintJobParams->media_tray = (media_tray_t) (*env)->GetIntField(
721             env, javaJobParams, _LocalJobParamsField__media_tray);
722     wprintJobParams->num_copies = (unsigned int) (*env)->GetIntField(
723             env, javaJobParams, _LocalJobParamsField__num_copies);
724     wprintJobParams->borderless = (bool) (*env)->GetIntField(env, javaJobParams,
725             _LocalJobParamsField__borderless);
726     wprintJobParams->render_flags = (unsigned int) (*env)->GetIntField(
727             env, javaJobParams, _LocalJobParamsField__render_flags);
728     wprintJobParams->pdf_render_resolution =
729             (unsigned int) (*env)->GetIntField(env, javaJobParams,
730                     _LocalJobParamsField__pdf_render_resolution);
731     // job margin setting
732     wprintJobParams->job_top_margin = (float) (*env)->GetFloatField(
733             env, javaJobParams, _LocalJobParamsField__job_margin_top);
734     wprintJobParams->job_left_margin = (float) (*env)->GetFloatField(
735             env, javaJobParams, _LocalJobParamsField__job_margin_left);
736     wprintJobParams->job_right_margin = (float) (*env)->GetFloatField(
737             env, javaJobParams, _LocalJobParamsField__job_margin_right);
738     wprintJobParams->job_bottom_margin = (float) (*env)->GetFloatField(
739             env, javaJobParams, _LocalJobParamsField__job_margin_bottom);
740 
741     if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__portrait_mode)) {
742         wprintJobParams->render_flags |= RENDER_FLAG_PORTRAIT_MODE;
743     } else if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__landscape_mode)) {
744         wprintJobParams->render_flags |= RENDER_FLAG_LANDSCAPE_MODE;
745     } else if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__auto_rotate)) {
746         wprintJobParams->render_flags |= RENDER_FLAG_AUTO_ROTATE;
747     }
748     if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__fill_page)) {
749         wprintJobParams->render_flags |= AUTO_SCALE_RENDER_FLAGS;
750     } else if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__fit_to_page)) {
751         wprintJobParams->render_flags |= AUTO_FIT_RENDER_FLAGS;
752         if ((*env)->GetBooleanField(env, javaJobParams, _LocalJobParamsField__document_scaling)) {
753             wprintJobParams->render_flags |= RENDER_FLAG_DOCUMENT_SCALING;
754         }
755     }
756 
757     int alignment = ((*env)->GetIntField(env, javaJobParams, _LocalJobParamsField__alignment));
758     if (alignment != 0) {
759         wprintJobParams->render_flags &= ~(RENDER_FLAG_CENTER_VERTICAL |
760                 RENDER_FLAG_CENTER_HORIZONTAL |
761                 RENDER_FLAG_CENTER_ON_ORIENTATION);
762         if (alignment & ((*env)->GetStaticIntField(
763                 env, _PrintServiceStringsClass,
764                 _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL))) {
765             wprintJobParams->render_flags |= RENDER_FLAG_CENTER_HORIZONTAL;
766         }
767         if (alignment & ((*env)->GetStaticIntField(
768                 env, _PrintServiceStringsClass,
769                 _PrintServiceStringsField__ALIGNMENT__CENTER_VERTICAL))) {
770             wprintJobParams->render_flags |= RENDER_FLAG_CENTER_VERTICAL;
771         }
772         if (alignment & ((*env)->GetStaticIntField(
773                 env, _PrintServiceStringsClass,
774                 _PrintServiceStringsField__ALIGNMENT__CENTER_HORIZONTAL_ON_ORIENTATION))) {
775             wprintJobParams->render_flags |= RENDER_FLAG_CENTER_ON_ORIENTATION;
776         }
777         if ((alignment & ((*env)->GetStaticIntField(
778                 env, _PrintServiceStringsClass, _PrintServiceStringsField__ALIGNMENT__CENTER))) ==
779                 ((*env)->GetStaticIntField(env, _PrintServiceStringsClass,
780                         _PrintServiceStringsField__ALIGNMENT__CENTER))) {
781             wprintJobParams->render_flags &= ~RENDER_FLAG_CENTER_ON_ORIENTATION;
782             wprintJobParams->render_flags |= (RENDER_FLAG_CENTER_VERTICAL |
783                     RENDER_FLAG_CENTER_HORIZONTAL);
784         }
785     }
786 
787     jstring docCategory = (jstring) (*env)->GetObjectField(env, javaJobParams,
788             _LocalJobParamsField__document_category);
789     if (docCategory != NULL) {
790         const char *category = (*env)->GetStringUTFChars(env, docCategory, NULL);
791         if (category != NULL) {
792             strncpy(wprintJobParams->docCategory, category,
793                     sizeof(wprintJobParams->docCategory) - 1);
794             (*env)->ReleaseStringUTFChars(env, docCategory, category);
795         }
796     }
797     // job name
798     jstring jobName = (jstring) (*env)->GetObjectField(env, javaJobParams,
799             _LocalJobParamsField__job_name);
800     if (jobName != NULL) {
801         const char *name = (*env)->GetStringUTFChars(env, jobName, NULL);
802         if (name != NULL) {
803             strncpy(wprintJobParams->job_name, name, sizeof(wprintJobParams->job_name) - 1);
804             (*env)->ReleaseStringUTFChars(env, jobName, name);
805         }
806     }
807     // job originating user name
808     jstring jobOriginatingUserName = (jstring) (*env)->GetObjectField(
809             env, javaJobParams, _LocalJobParamsField__job_originating_user_name);
810     if (jobOriginatingUserName != NULL) {
811         const char *name = (*env)->GetStringUTFChars(env, jobOriginatingUserName, NULL);
812         if (name != NULL) {
813             strncpy(wprintJobParams->job_originating_user_name, name,
814                     sizeof(wprintJobParams->job_originating_user_name) - 1);
815             (*env)->ReleaseStringUTFChars(env, jobOriginatingUserName, name);
816         }
817     }
818 
819     free(wprintJobParams->page_range);
820     wprintJobParams->page_range = NULL;
821     jstring pageRangeObject = (jstring) (*env)->GetObjectField(env, javaJobParams,
822             _LocalJobParamsField__page_range);
823     if (pageRangeObject) {
824         int page_range_size = (*env)->GetStringLength(env, pageRangeObject);
825         const jbyte *pageRange = (jbyte *) (*env)->GetStringUTFChars(env, pageRangeObject, 0);
826         if (strcmp((char *) pageRange, "") != 0) {
827             wprintJobParams->page_range = (char *) malloc(page_range_size + 1);
828             memset(wprintJobParams->page_range, 0, page_range_size + 1);
829             strncpy(wprintJobParams->page_range, (char *) pageRange, page_range_size);
830 
831             (*env)->ReleaseStringUTFChars(env, pageRangeObject, (const char *) pageRange);
832         }
833     }
834 
835     return OK;
836 }
837 
838 /*
839  * Converts wprintJobParams to java and saves them to javaJobParams
840  */
_covertJobParams_to_Java(JNIEnv * env,jobject javaJobParams,wprint_job_params_t * wprintJobParams)841 static int _covertJobParams_to_Java(JNIEnv *env, jobject javaJobParams,
842         wprint_job_params_t *wprintJobParams) {
843     if (!javaJobParams || !wprintJobParams) {
844         return ERROR;
845     }
846 
847     jbyteArray nativeDataObject = (jbyteArray) (*env)->GetObjectField(
848             env, javaJobParams, _LocalJobParamsField__nativeData);
849     if (!nativeDataObject) {
850         nativeDataObject = (*env)->NewByteArray(env, sizeof(wprint_job_params_t));
851         (*env)->SetObjectField(env, javaJobParams, _LocalJobParamsField__nativeData,
852                 nativeDataObject);
853         nativeDataObject = (jbyteArray) (*env)->GetObjectField(env, javaJobParams,
854                 _LocalJobParamsField__nativeData);
855     }
856 
857     jbyte *nativeDataPtr = (*env)->GetByteArrayElements(env, nativeDataObject, NULL);
858     memcpy((void *) nativeDataPtr, wprintJobParams, sizeof(wprint_job_params_t));
859     (*env)->ReleaseByteArrayElements(env, nativeDataObject, nativeDataPtr, 0);
860 
861     // update job parameters
862     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__media_size,
863             (int) wprintJobParams->media_size);
864     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__media_type,
865             (int) wprintJobParams->media_type);
866     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__duplex,
867             (int) wprintJobParams->duplex);
868     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__color_space,
869             (int) wprintJobParams->color_space);
870     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__media_tray,
871             (int) wprintJobParams->media_tray);
872     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__num_copies,
873             (int) wprintJobParams->num_copies);
874     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__borderless,
875             (int) wprintJobParams->borderless);
876     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__render_flags,
877             (int) wprintJobParams->render_flags);
878     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__pdf_render_resolution,
879             wprintJobParams->pdf_render_resolution);
880     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__fit_to_page,
881             (jboolean) ((wprintJobParams->render_flags & AUTO_FIT_RENDER_FLAGS) ==
882                     AUTO_FIT_RENDER_FLAGS));
883     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__fill_page,
884             (jboolean) ((wprintJobParams->render_flags & AUTO_SCALE_RENDER_FLAGS) ==
885                     AUTO_SCALE_RENDER_FLAGS));
886     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__auto_rotate,
887             (jboolean) ((wprintJobParams->render_flags & RENDER_FLAG_AUTO_ROTATE) != 0));
888     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__portrait_mode, (jboolean) (
889             (wprintJobParams->render_flags & RENDER_FLAG_PORTRAIT_MODE) != 0));
890     (*env)->SetBooleanField(env, javaJobParams, _LocalJobParamsField__landscape_mode, (jboolean) (
891             (wprintJobParams->render_flags & RENDER_FLAG_LANDSCAPE_MODE) != 0));
892 
893     // update the printable area & DPI information
894     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__print_resolution,
895             (int) wprintJobParams->pixel_units);
896     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__printable_width,
897             (int) wprintJobParams->width);
898     (*env)->SetIntField(env, javaJobParams, _LocalJobParamsField__printable_height,
899             (int) wprintJobParams->height);
900 
901     // update the page size information
902     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_width,
903             wprintJobParams->page_width);
904     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_height,
905             wprintJobParams->page_height);
906     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_top,
907             wprintJobParams->page_top_margin);
908     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_left,
909             wprintJobParams->page_left_margin);
910     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_right,
911             wprintJobParams->page_right_margin);
912     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__page_margin_bottom,
913             wprintJobParams->page_bottom_margin);
914 
915     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_top,
916             wprintJobParams->job_top_margin);
917     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_left,
918             wprintJobParams->job_left_margin);
919     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_right,
920             wprintJobParams->job_right_margin);
921     (*env)->SetFloatField(env, javaJobParams, _LocalJobParamsField__job_margin_bottom,
922             wprintJobParams->job_bottom_margin);
923 
924     return OK;
925 }
926 
927 /*
928  * Handles print job callbacks. Handles job states and blocked reasons
929  */
_wprint_callback_fn(wJob_t job_handle,void * param)930 static void _wprint_callback_fn(wJob_t job_handle, void *param) {
931     jstring jStr;
932     wprint_job_callback_params_t *cb_param = (wprint_job_callback_params_t *) param;
933     if (!cb_param) {
934         return;
935     }
936 
937     int needDetach = 0;
938     JNIEnv *env;
939     if ((*_JVM)->GetEnv(_JVM, (void **) &env, JNI_VERSION_1_6) < 0) {
940         needDetach = 1;
941         if ((*_JVM)->AttachCurrentThread(_JVM, &env, NULL) < 0) {
942             return;
943         }
944     }
945 
946     jobject callbackParams = (*env)->NewObject(env, _JobCallbackParamsClass,
947             _JobCallbackParamsMethod__init);
948     if (callbackParams != 0) {
949         switch (cb_param->state) {
950             case JOB_QUEUED:
951                 jStr = (jstring) (*env)->GetStaticObjectField(
952                         env, _PrintServiceStringsClass,
953                         _PrintServiceStringsField__JOB_STATE_QUEUED);
954                 break;
955             case JOB_RUNNING:
956                 jStr = (jstring) (*env)->GetStaticObjectField(
957                         env, _PrintServiceStringsClass,
958                         _PrintServiceStringsField__JOB_STATE_RUNNING);
959                 break;
960             case JOB_BLOCKED:
961                 jStr = (jstring) (*env)->GetStaticObjectField(
962                         env, _PrintServiceStringsClass,
963                         _PrintServiceStringsField__JOB_STATE_BLOCKED);
964                 break;
965             case JOB_DONE:
966                 jStr = (jstring) (*env)->GetStaticObjectField(
967                         env, _PrintServiceStringsClass,
968                         _PrintServiceStringsField__JOB_STATE_DONE);
969                 break;
970             default:
971                 jStr = (jstring) (*env)->GetStaticObjectField(
972                         env, _PrintServiceStringsClass,
973                         _PrintServiceStringsField__JOB_STATE_OTHER);
974                 break;
975         }
976         (*env)->SetObjectField(env, callbackParams, _JobCallbackParamsField__jobState, jStr);
977 
978         if (cb_param->state == JOB_DONE) {
979             switch (cb_param->job_done_result) {
980                 case OK:
981                     jStr = (jstring) (*env)->GetStaticObjectField(
982                             env, _PrintServiceStringsClass,
983                             _PrintServiceStringsField__JOB_DONE_OK);
984                     break;
985                 case ERROR:
986                     jStr = (jstring) (*env)->GetStaticObjectField(
987                             env, _PrintServiceStringsClass,
988                             _PrintServiceStringsField__JOB_DONE_ERROR);
989                     break;
990                 case CANCELLED:
991                     jStr = (jstring) (*env)->GetStaticObjectField(
992                             env, _PrintServiceStringsClass,
993                             _PrintServiceStringsField__JOB_DONE_CANCELLED);
994                     break;
995                 case CORRUPT:
996                     jStr = (jstring) (*env)->GetStaticObjectField(
997                             env, _PrintServiceStringsClass,
998                             _PrintServiceStringsField__JOB_DONE_CORRUPT);
999                     break;
1000                 default:
1001                     jStr = (jstring) (*env)->GetStaticObjectField(
1002                             env, _PrintServiceStringsClass,
1003                             _PrintServiceStringsField__JOB_DONE_OTHER);
1004                     break;
1005             }
1006 
1007             (*env)->SetObjectField(env, callbackParams,
1008                     _JobCallbackParamsField__jobDoneResult, jStr);
1009         }
1010 
1011         int i, count;
1012         for (count = i = 0; i < PRINT_STATUS_MAX_STATE; i++) {
1013             if (cb_param->blocked_reasons & (1 << i)) {
1014                 count++;
1015             }
1016         }
1017 
1018         if (count > 0) {
1019             jStr = (*env)->NewStringUTF(env, "");
1020             jobjectArray stringArray = (*env)->NewObjectArray(env, count, (*env)->FindClass(
1021                     env, "java/lang/String"), jStr);
1022             (*env)->DeleteLocalRef(env, jStr);
1023 
1024             unsigned int blocked_reasons = cb_param->blocked_reasons;
1025             for (count = i = 0; i < PRINT_STATUS_MAX_STATE; i++) {
1026                 jStr = NULL;
1027 
1028                 if ((blocked_reasons & (1 << i)) == 0) {
1029                     jStr = NULL;
1030                 } else if (blocked_reasons & BLOCKED_REASON_UNABLE_TO_CONNECT) {
1031                     jStr = (jstring) (*env)->GetStaticObjectField(
1032                             env, _PrintServiceStringsClass,
1033                             _PrintServiceStringsField__BLOCKED_REASON__OFFLINE);
1034                 } else if (blocked_reasons & BLOCKED_REASON_BUSY) {
1035                     jStr = (jstring) (*env)->GetStaticObjectField(
1036                             env, _PrintServiceStringsClass,
1037                             _PrintServiceStringsField__BLOCKED_REASON__BUSY);
1038                 } else if (blocked_reasons & BLOCKED_REASONS_CANCELLED) {
1039                     jStr = (jstring) (*env)->GetStaticObjectField(
1040                             env, _PrintServiceStringsClass,
1041                             _PrintServiceStringsField__BLOCKED_REASON__CANCELLED);
1042                 } else if (blocked_reasons & BLOCKED_REASON_JAMMED) {
1043                     jStr = (jstring) (*env)->GetStaticObjectField(
1044                             env, _PrintServiceStringsClass,
1045                             _PrintServiceStringsField__BLOCKED_REASON__JAMMED);
1046                 } else if (blocked_reasons & BLOCKED_REASON_OUT_OF_PAPER) {
1047                     jStr = (jstring) (*env)->GetStaticObjectField(
1048                             env, _PrintServiceStringsClass,
1049                             _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_PAPER);
1050                 } else if (blocked_reasons & BLOCKED_REASON_OUT_OF_INK) {
1051                     jStr = (jstring) (*env)->GetStaticObjectField(
1052                             env, _PrintServiceStringsClass,
1053                             _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_INK);
1054                 } else if (blocked_reasons & BLOCKED_REASON_OUT_OF_TONER) {
1055                     jStr = (jstring) (*env)->GetStaticObjectField(
1056                             env, _PrintServiceStringsClass,
1057                             _PrintServiceStringsField__BLOCKED_REASON__OUT_OF_TONER);
1058                 } else if (blocked_reasons & BLOCKED_REASON_DOOR_OPEN) {
1059                     jStr = (jstring) (*env)->GetStaticObjectField(
1060                             env, _PrintServiceStringsClass,
1061                             _PrintServiceStringsField__BLOCKED_REASON__DOOR_OPEN);
1062                 } else if (blocked_reasons & BLOCKED_REASON_SVC_REQUEST) {
1063                     jStr = (jstring) (*env)->GetStaticObjectField(
1064                             env, _PrintServiceStringsClass,
1065                             _PrintServiceStringsField__BLOCKED_REASON__SERVICE_REQUEST);
1066                 } else if (blocked_reasons & BLOCKED_REASON_LOW_ON_INK) {
1067                     jStr = (jstring) (*env)->GetStaticObjectField(
1068                             env, _PrintServiceStringsClass,
1069                             _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_INK);
1070                 } else if (blocked_reasons & BLOCKED_REASON_LOW_ON_TONER) {
1071                     jStr = (jstring) (*env)->GetStaticObjectField(
1072                             env, _PrintServiceStringsClass,
1073                             _PrintServiceStringsField__BLOCKED_REASON__LOW_ON_TONER);
1074                 } else if (blocked_reasons &
1075                         BLOCKED_REASON_PRINT_STATUS_VERY_LOW_ON_INK) {
1076                     jStr = (jstring) (*env)->GetStaticObjectField(
1077                             env, _PrintServiceStringsClass,
1078                             _PrintServiceStringsField__BLOCKED_REASON__REALLY_LOW_ON_INK);
1079                 } else if (blocked_reasons & BLOCKED_REASON_UNKNOWN) {
1080                     jStr = (jstring) (*env)->GetStaticObjectField(
1081                             env, _PrintServiceStringsClass,
1082                             _PrintServiceStringsField__BLOCKED_REASON__UNKNOWN);
1083                 }
1084 
1085                 blocked_reasons &= ~(1 << i);
1086                 if (jStr != 0) {
1087                     (*env)->SetObjectArrayElement(env, stringArray, count++, jStr);
1088                 }
1089             }
1090 
1091             (*env)->SetObjectField(env, callbackParams, _JobCallbackParamsField__blockedReasons,
1092                     stringArray);
1093         }
1094 
1095         (*env)->SetIntField(env, callbackParams, _JobCallbackParamsField__jobId,
1096                 (jint) job_handle);
1097         (*env)->CallVoidMethod(env, _callbackReceiver, _JobCallbackMethod__jobCallback,
1098                 (jint) job_handle, callbackParams);
1099         (*env)->DeleteLocalRef(env, callbackParams);
1100     }
1101 
1102     if (needDetach) {
1103         (*_JVM)->DetachCurrentThread(_JVM);
1104     }
1105 }
1106 
1107 /*
1108  * Initialize wprint JNI
1109  */
Java_com_android_bips_ipp_Backend_nativeInit(JNIEnv * env,jobject obj,jobject callbackReceiver,jstring fakeDir,jint apiVersion)1110 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeInit(
1111         JNIEnv *env, jobject obj, jobject callbackReceiver, jstring fakeDir,
1112         jint apiVersion) {
1113     LOGI("nativeInit JNIenv is %p", env);
1114     int result;
1115 
1116     // Setup the global JavaVM reference first.
1117     (*env)->GetJavaVM(env, &_JVM);
1118 
1119     // Initialize the Android API version value
1120     g_API_version = apiVersion;
1121 
1122     _initJNI(env, callbackReceiver, fakeDir);
1123 
1124     // initialize wprint library
1125     result = wprintInit();
1126 
1127     // return the result
1128     return result;
1129 }
1130 
1131 /*
1132  * Copies a given string and returns the copy
1133  */
copyToNewString(JNIEnv * env,jstring source)1134 static char *copyToNewString(JNIEnv *env, jstring source) {
1135     const char *fromJava;
1136     char *newString;
1137 
1138     fromJava = (*env)->GetStringUTFChars(env, source, NULL);
1139     if (fromJava == NULL) return NULL;
1140 
1141     newString = (char *) malloc(strlen(fromJava) + 1);
1142     strcpy(newString, fromJava);
1143     (*env)->ReleaseStringUTFChars(env, source, fromJava);
1144 
1145     return newString;
1146 }
1147 
1148 /*
1149  * JNI call to wprint to get capabilities. Returns caps converted to java.
1150  */
Java_com_android_bips_ipp_Backend_nativeGetCapabilities(JNIEnv * env,jobject obj,jstring address,jint port,jstring httpResource,jstring uriScheme,jlong timeout,jobject printerCaps)1151 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeGetCapabilities(
1152         JNIEnv *env, jobject obj, jstring address, jint port, jstring httpResource,
1153         jstring uriScheme, jlong timeout, jobject printerCaps) {
1154     jint result;
1155     printer_capabilities_t caps;
1156     wprint_connect_info_t connect_info;
1157 
1158     connect_info.printer_addr = copyToNewString(env, address);
1159     connect_info.uri_path = copyToNewString(env, httpResource);
1160     connect_info.uri_scheme = copyToNewString(env, uriScheme);
1161     connect_info.port_num = port;
1162     connect_info.timeout = timeout;
1163 
1164     LOGI("nativeGetCapabilities for %s JNIenv is %p", connect_info.printer_addr, env);
1165 
1166     // This call may take a while, and the JNI may be torn down when we return
1167     result = wprintGetCapabilities(&connect_info, &caps);
1168 
1169     if (connect_info.printer_addr) free((char *) connect_info.printer_addr);
1170     if (connect_info.uri_path) free((char *) connect_info.uri_path);
1171     if (connect_info.uri_scheme) free((char *) connect_info.uri_scheme);
1172 
1173     if (!wprintIsRunning() && result == 0) {
1174         result = ERROR;
1175     }
1176 
1177     // additional IPP checks
1178     if (result == 0) {
1179         if (caps.isSupported && (caps.ippVersionMajor < 1)) {
1180             caps.isSupported = 0;
1181         }
1182         _convertPrinterCaps_to_Java(env, printerCaps, &caps);
1183     }
1184 
1185     return result;
1186 }
1187 
1188 /*
1189  * JNI call to wprint to get default job params. Returns job params converted to java.
1190  */
Java_com_android_bips_ipp_Backend_nativeGetDefaultJobParameters(JNIEnv * env,jobject obj,jobject jobParams)1191 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeGetDefaultJobParameters(
1192         JNIEnv *env, jobject obj, jobject jobParams) {
1193     LOGI("nativeGetDefaultJobParameters, JNIenv is %p", env);
1194     jint result;
1195     wprint_job_params_t params;
1196 
1197     result = wprintGetDefaultJobParams(&params);
1198 
1199     _covertJobParams_to_Java(env, jobParams, &params);
1200     return result;
1201 }
1202 
1203 /*
1204  * JNI call to wprint to get final job params. Returns final params converted to java.
1205  */
Java_com_android_bips_ipp_Backend_nativeGetFinalJobParameters(JNIEnv * env,jobject obj,jobject jobParams,jobject printerCaps)1206 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeGetFinalJobParameters(
1207         JNIEnv *env, jobject obj, jobject jobParams, jobject printerCaps) {
1208     LOGI("nativeGetFinalJobParameters, JNIenv is %p", env);
1209     jint result;
1210     wprint_job_params_t params;
1211     printer_capabilities_t caps;
1212 
1213     _convertJobParams_to_C(env, jobParams, &params);
1214     _convertPrinterCaps_to_C(env, printerCaps, &caps);
1215 
1216     LOGD("nativeGetFinalJobParameters: After _convertJobParams_to_C: res=%d, name=%s",
1217             params.pdf_render_resolution, params.job_name);
1218     result = wprintGetFinalJobParams(&params, &caps);
1219 
1220     _covertJobParams_to_Java(env, jobParams, &params);
1221     return result;
1222 }
1223 
1224 /*
1225  * JNI call to wprint to start a print job. Takes connection params, job params, caps, and file
1226  * array to complete the job
1227  */
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)1228 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeStartJob(
1229         JNIEnv *env, jobject obj, jstring address, jint port, jstring mimeType, jobject jobParams,
1230         jobject printerCaps, jobject fileArray, jstring jobDebugDir, jstring scheme) {
1231     LOGI("nativeStartJob, JNIenv is %p", env);
1232     jint result = ERROR;
1233     wJob_t job_handle = ERROR;
1234     bool hasFiles = false;
1235 
1236     wprint_job_params_t params;
1237     printer_capabilities_t caps;
1238 
1239     _convertJobParams_to_C(env, jobParams, &params);
1240     _convertPrinterCaps_to_C(env, printerCaps, &caps);
1241 
1242     LOGD("nativeStartJob: After _convertJobParams_to_C: res=%d, name=%s",
1243             params.pdf_render_resolution, params.job_name);
1244 
1245     const char *addressStr = (*env)->GetStringUTFChars(env, address, NULL);
1246     const char *mimeTypeStr = (*env)->GetStringUTFChars(env, mimeType, NULL);
1247     const char *dataDirStr = (*env)->GetStringUTFChars(env, _fakeDir, NULL);
1248     const char *schemeStr = (*env)->GetStringUTFChars(env, scheme, NULL);
1249 
1250     jsize len = 0;
1251     jobjectArray array;
1252 
1253     if (fileArray) {
1254         array = (jobjectArray) fileArray;
1255         len = (*env)->GetArrayLength(env, array);
1256         hasFiles = (len > 0);
1257     }
1258 
1259     int index = 0, pageIndex, incrementor;
1260     int page_range_arr[len];
1261 
1262     // Initialize page_range_arr (address defect reported by Coverity scans)
1263     memset((char *) page_range_arr, 0, sizeof(int) * len);
1264 
1265     int pdf_pages_ary[len];
1266     int pages_ary[len][MAX_NUM_PAGES];
1267 
1268     if (hasFiles) {
1269         result = OK;
1270         for (pageIndex = 0; ((result == OK) && (pageIndex < len)); pageIndex++) {
1271             jstring page = (jstring) (*env)->GetObjectArrayElement(env, array, pageIndex);
1272             const char *pageStr = (*env)->GetStringUTFChars(env, page, NULL);
1273             if (pageStr == NULL) {
1274                 result = ERROR;
1275             } else {
1276                 int page_count = 0;
1277                 if (_get_pdf_page_count(mimeTypeStr, &page_count, pageStr)) {
1278                     pdf_pages_ary[pageIndex] = page_count;
1279                     page_range_arr[pageIndex] = 0;
1280                     char page_range_str[MAX_NUM_PAGES];
1281                     memset(page_range_str, 0, MAX_NUM_PAGES);
1282                     _get_pdf_page_range(env, jobParams, &pages_ary[pageIndex][0],
1283                             pdf_pages_ary[pageIndex], &page_range_arr[pageIndex], page_range_str);
1284                 }
1285             }
1286             (*env)->ReleaseStringUTFChars(env, page, pageStr);
1287         }
1288 
1289         jstring page = (jstring) (*env)->GetObjectArrayElement(env, array, index);
1290         const char *pageStr = (*env)->GetStringUTFChars(env, page, NULL);
1291         if (pageStr == NULL) {
1292             result = ERROR;
1293         }
1294 
1295         if (len == 1) {
1296             if (_is_pdf_doc((char *) mimeTypeStr, (char *) pageStr)) {
1297                 if (page_range_arr[0] == 1) {
1298                     LOGI("smart duplex, disabling duplex");
1299                     params.duplex = DUPLEX_MODE_NONE;
1300                 }
1301             } else {
1302                 LOGI("smart duplex, disabling duplex");
1303                 params.duplex = DUPLEX_MODE_NONE;
1304             }
1305         }
1306 
1307         (*env)->ReleaseStringUTFChars(env, page, pageStr);
1308         const char *jobDebugDirStr = NULL;
1309         if (jobDebugDir != NULL) {
1310             jobDebugDirStr = (*env)->GetStringUTFChars(env, jobDebugDir, NULL);
1311         }
1312         result = wprintStartJob(addressStr, port, &params, &caps, (char *) mimeTypeStr,
1313                 (char *) dataDirStr, _wprint_callback_fn, jobDebugDirStr, schemeStr);
1314         if (result == ERROR) {
1315             LOGE("failed to start job: error code :%d", errno);
1316         }
1317         if ((jobDebugDir != NULL) && (jobDebugDirStr != NULL)) {
1318             (*env)->ReleaseStringUTFChars(env, jobDebugDir, jobDebugDirStr);
1319         }
1320     } else {
1321         LOGE("empty file list");
1322     }
1323     if (result != ERROR) {
1324         job_handle = (wJob_t) result;
1325 
1326         // register job handle with service
1327         if (caps.faceDownTray || params.duplex) {
1328             index = 0;
1329             incrementor = 1;
1330         } else {
1331             index = len - 1;
1332             incrementor = -1;
1333         }
1334 
1335         result = OK;
1336         for (pageIndex = 1; ((result == OK) && (pageIndex <= len)); pageIndex++) {
1337             jstring page = (jstring) (*env)->GetObjectArrayElement(env, array, index);
1338             const char *pageStr = (*env)->GetStringUTFChars(env, page, NULL);
1339             if (pageStr == NULL) {
1340                 result = ERROR;
1341             } else {
1342                 if (_is_pdf_doc((char *) mimeTypeStr, (char *) pageStr)) {
1343                     result = _print_pdf_pages(job_handle, &caps, params.duplex, (char *) pageStr,
1344                             page_range_arr[index], pages_ary[index]);
1345                 } else {
1346                     result = wprintPage(job_handle, pageIndex, (char *) pageStr, false, false,
1347                             0, 0, 0, 0);
1348                 }
1349             }
1350             (*env)->ReleaseStringUTFChars(env, page, pageStr);
1351             index += incrementor;
1352         }
1353 
1354         wprintPage(job_handle, pageIndex, NULL, true, false, 0, 0, 0, 0);
1355         if (result != OK) {
1356             LOGE("failed to add some pages, aborting job");
1357             wprintCancelJob(job_handle);
1358             wprintEndJob(job_handle);
1359             job_handle = ERROR;
1360         }
1361     }
1362 
1363     (*env)->ReleaseStringUTFChars(env, mimeType, mimeTypeStr);
1364     (*env)->ReleaseStringUTFChars(env, address, addressStr);
1365     (*env)->ReleaseStringUTFChars(env, _fakeDir, dataDirStr);
1366     (*env)->ReleaseStringUTFChars(env, scheme, schemeStr);
1367     return job_handle;
1368 }
1369 
1370 /*
1371  * JNI call to wprint to end a print job
1372  */
Java_com_android_bips_ipp_Backend_nativeEndJob(JNIEnv * env,jobject obj,jint job_handle)1373 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeEndJob(
1374         JNIEnv *env, jobject obj, jint job_handle) {
1375     LOGI("nativeEndJob, JNIenv is %p", env);
1376     return wprintEndJob((wJob_t) job_handle);
1377 }
1378 
1379 /*
1380  * JNI call to wprint to cancel a print job
1381  */
Java_com_android_bips_ipp_Backend_nativeCancelJob(JNIEnv * env,jobject obj,jint job_handle)1382 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeCancelJob(
1383         JNIEnv *env, jobject obj, jint job_handle) {
1384     LOGI("nativeCancelJob, JNIenv is %p", env);
1385     return wprintCancelJob((wJob_t) job_handle);
1386 }
1387 
1388 /*
1389  * JNI call to wprint to exit
1390  */
Java_com_android_bips_ipp_Backend_nativeExit(JNIEnv * env,jobject obj)1391 JNIEXPORT jint JNICALL Java_com_android_bips_ipp_Backend_nativeExit(JNIEnv *env, jobject obj) {
1392     LOGI("nativeExit, JNIenv is %p", env);
1393 
1394     (*env)->DeleteGlobalRef(env, _LocalJobParamsClass);
1395     (*env)->DeleteGlobalRef(env, _LocalPrinterCapabilitiesClass);
1396     (*env)->DeleteGlobalRef(env, _JobCallbackParamsClass);
1397     if (_callbackReceiver) {
1398         (*env)->DeleteGlobalRef(env, _callbackReceiver);
1399     }
1400     if (_JobCallbackClass) {
1401         (*env)->DeleteGlobalRef(env, _JobCallbackClass);
1402     }
1403     (*env)->DeleteGlobalRef(env, _fakeDir);
1404     (*env)->DeleteGlobalRef(env, _PrintServiceStringsClass);
1405 
1406     pdf_render_deinit(env);
1407     return wprintExit();
1408 }
1409 
1410 /*
1411  * Sets app name/version and os name
1412  */
Java_com_android_bips_ipp_Backend_nativeSetSourceInfo(JNIEnv * env,jobject obj,jstring appName,jstring appVersion,jstring osName)1413 JNIEXPORT void JNICALL Java_com_android_bips_ipp_Backend_nativeSetSourceInfo(
1414         JNIEnv *env, jobject obj, jstring appName, jstring appVersion, jstring osName) {
1415     LOGI("nativeSetSourceInfo, JNIenv is %p", env);
1416     const char *appNameStr = (*env)->GetStringUTFChars(env, appName, NULL);
1417     const char *appVersionStr = (*env)->GetStringUTFChars(env, appVersion, NULL);
1418     const char *osNameStr = (*env)->GetStringUTFChars(env, osName, NULL);
1419     wprintSetSourceInfo(appNameStr, appVersionStr, osNameStr);
1420     (*env)->ReleaseStringUTFChars(env, appName, appNameStr);
1421     (*env)->ReleaseStringUTFChars(env, appVersion, appVersionStr);
1422     (*env)->ReleaseStringUTFChars(env, osName, osNameStr);
1423 }