Snap for 4380782 from fb37766f9429cb26f003c9e81b909637544ff8b4 to oc-mr1-release

Change-Id: Iecb8e89d622c67e67853f38872e3e9c65a712ddf
diff --git a/jni/include/ifc_print_job.h b/jni/include/ifc_print_job.h
index 1efaf45..0c0fc2a 100644
--- a/jni/include/ifc_print_job.h
+++ b/jni/include/ifc_print_job.h
@@ -29,7 +29,7 @@
      * Initializes print job handle with given connection params.
      */
     status_t (*init)(const struct ifc_print_job_st *this_p, const char *printer_address, int port,
-            const char *printer_uri);
+            const char *printer_uri, bool use_secure_uri);
 
     /*
      * Validates job and connection params, updating parameters as necessary.
diff --git a/jni/include/lib_wprint.h b/jni/include/lib_wprint.h
index 3703a3d..006f6c1 100644
--- a/jni/include/lib_wprint.h
+++ b/jni/include/lib_wprint.h
@@ -292,7 +292,7 @@
 wJob_t wprintStartJob(const char *printer_addr, port_t port_num,
         const wprint_job_params_t *job_params, const printer_capabilities_t *printer_cap,
         const char *mime_type, const char *pathname, wprint_status_cb_t cb_fn,
-        const char *debugDir);
+        const char *debugDir, const char *scheme);
 
 /*
  * Sent once per job at the end of the job. A current print job must end for the next one
diff --git a/jni/ipphelper/ipp_print.c b/jni/ipphelper/ipp_print.c
index 3bcc0bb..57914b3 100644
--- a/jni/ipphelper/ipp_print.c
+++ b/jni/ipphelper/ipp_print.c
@@ -26,7 +26,7 @@
 #define TAG "ipp_print"
 
 static status_t _init(const ifc_print_job_t *this_p, const char *printer_address, int port,
-        const char *printer_uri);
+        const char *printer_uri, bool use_secure_uri);
 
 static status_t _validate_job(const ifc_print_job_t *this_p, wprint_job_params_t *job_params);
 
@@ -75,7 +75,7 @@
 }
 
 static status_t _init(const ifc_print_job_t *this_p, const char *printer_address, int port,
-        const char *printer_uri) {
+        const char *printer_uri, bool use_secure_uri) {
     LOGD("_init: Enter");
     ipp_print_job_t *ipp_job;
     const char *ipp_scheme;
@@ -95,12 +95,21 @@
 
     int ippPortNumber = ((port == IPP_PORT) ? ippPort() : port);
     LOGD("Normal URI for %s:%d", printer_address, ippPortNumber);
-    ipp_scheme = IPP_PREFIX;
+    ipp_scheme = (use_secure_uri) ? IPPS_PREFIX : IPP_PREFIX;
 
     httpAssembleURIf(HTTP_URI_CODING_ALL, ipp_job->printer_uri, sizeof(ipp_job->printer_uri),
             ipp_scheme, NULL, printer_address, ippPortNumber, printer_uri);
     getResourceFromURI(ipp_job->printer_uri, ipp_job->http_resource, 1024);
-    ipp_job->http = httpConnect(printer_address, ippPortNumber);
+    if (use_secure_uri) {
+        ipp_job->http = httpConnectEncrypt(printer_address, ippPortNumber, HTTP_ENCRYPTION_ALWAYS);
+
+        // If ALWAYS doesn't work, fall back to REQUIRED
+        if (ipp_job->http == NULL) {
+            ipp_job->http = httpConnectEncrypt(printer_address, ippPortNumber, HTTP_ENCRYPT_REQUIRED);
+        }
+    } else {
+        ipp_job->http = httpConnectEncrypt(printer_address, ippPortNumber, HTTP_ENCRYPTION_IF_REQUESTED);
+    }
 
     httpSetTimeout(ipp_job->http, DEFAULT_IPP_TIMEOUT, NULL, 0);
 
diff --git a/jni/ipphelper/ipphelper.c b/jni/ipphelper/ipphelper.c
index 2b16ed3..bbe484e 100644
--- a/jni/ipphelper/ipphelper.c
+++ b/jni/ipphelper/ipphelper.c
@@ -1425,7 +1425,16 @@
 
     int ippPortNumber = ((connect_info->port_num == IPP_PORT) ? ippPort() : connect_info->port_num);
 
-    curl_http = httpConnect(connect_info->printer_addr, ippPortNumber);
+    if (strstr(connect_info->uri_scheme,IPPS_PREFIX) != NULL) {
+        curl_http = httpConnectEncrypt(connect_info->printer_addr, ippPortNumber, HTTP_ENCRYPTION_ALWAYS);
+
+        // If ALWAYS doesn't work, fall back to REQUIRED
+        if (curl_http == NULL) {
+            curl_http = httpConnectEncrypt(connect_info->printer_addr, ippPortNumber, HTTP_ENCRYPT_REQUIRED);
+        }
+    } else {
+        curl_http = httpConnectEncrypt(connect_info->printer_addr, ippPortNumber, HTTP_ENCRYPTION_IF_REQUESTED);
+    }
 
     httpSetTimeout(curl_http, (double)connect_info->timeout / 1000, NULL, 0);
     httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, uriLength, connect_info->uri_scheme, NULL,
diff --git a/jni/ipphelper/ipphelper.h b/jni/ipphelper/ipphelper.h
index 15bd26a..bd93741 100644
--- a/jni/ipphelper/ipphelper.h
+++ b/jni/ipphelper/ipphelper.h
@@ -145,10 +145,11 @@
 ipp_t *ipp_doCupsRequest(http_t *http, ipp_t *request, char *http_resource, char *printer_uri);
 
 #define IPP_PREFIX "ipp"
+#define IPPS_PREFIX "ipps"
 #define DEFAULT_IPP_URI_RESOURCE "/ipp/print"
 
 #ifdef __cplusplus
 }
 #endif // __cplusplus
 
-#endif // !_IPP_HELPER_H_
\ No newline at end of file
+#endif // !_IPP_HELPER_H_
diff --git a/jni/lib/lib_wprint.c b/jni/lib/lib_wprint.c
index d905d86..e7aebfe 100644
--- a/jni/lib/lib_wprint.c
+++ b/jni/lib/lib_wprint.c
@@ -147,6 +147,7 @@
 
     wprint_job_params_t job_params;
     bool cancel_ok;
+    bool use_secure_uri;
 
     const ifc_status_monitor_t *status_ifc;
     char debug_path[MAX_PATHNAME_LENGTH + 1];
@@ -740,7 +741,11 @@
                 connect_info.printer_addr = jq->printer_addr;
                 connect_info.uri_path = jq->printer_uri;
                 connect_info.port_num = jq->port_num;
-                connect_info.uri_scheme = IPP_PREFIX;
+                if (jq->use_secure_uri) {
+                    connect_info.uri_scheme = IPPS_PREFIX;
+                } else {
+                    connect_info.uri_scheme = IPP_PREFIX;
+                }
                 connect_info.timeout = DEFAULT_IPP_TIMEOUT;
                 jq->status_ifc->init(jq->status_ifc, &connect_info);
             }
@@ -835,7 +840,7 @@
             if (job_result == OK) {
                 if (jq->print_ifc) {
                     job_result = jq->print_ifc->init(jq->print_ifc, jq->printer_addr,
-                            jq->port_num, jq->printer_uri);
+                            jq->port_num, jq->printer_uri, jq->use_secure_uri);
                     if (job_result == ERROR) {
                         jq->blocked_reasons = BLOCKED_REASON_UNABLE_TO_CONNECT;
                     }
@@ -1727,7 +1732,7 @@
 wJob_t wprintStartJob(const char *printer_addr, port_t port_num,
         const wprint_job_params_t *job_params, const printer_capabilities_t *printer_cap,
         const char *mime_type, const char *pathname, wprint_status_cb_t cb_fn,
-        const char *debugDir) {
+        const char *debugDir, const char *scheme) {
     wJob_t job_handle = WPRINT_BAD_JOB_HANDLE;
     _msg_t msg;
     struct stat stat_buf;
@@ -1810,6 +1815,8 @@
 
         memcpy((char *) &(jq->job_params), job_params, sizeof(wprint_job_params_t));
 
+        jq->use_secure_uri = (strstr(scheme, IPPS_PREFIX) != NULL);
+
         size_t useragent_len = strlen(USERAGENT_PREFIX) + strlen(jq->job_params.docCategory) + 1;
         char *useragent = (char *) malloc(useragent_len);
         if (useragent != NULL) {
@@ -2111,4 +2118,4 @@
     }
 
     LOGI("App Name: '%s', Version: '%s', OS: '%s'", g_appName, g_appVersion, g_osName);
-}
\ No newline at end of file
+}
diff --git a/jni/lib/printer.c b/jni/lib/printer.c
index 2ae0d7a..55eca67 100644
--- a/jni/lib/printer.c
+++ b/jni/lib/printer.c
@@ -45,7 +45,7 @@
 static long int _wprint_timeout_msec = DEFAULT_TIMEOUT;
 
 static status_t _init(const ifc_print_job_t *this_p, const char *printer_addr, int port,
-        const char *printer_uri) {
+        const char *printer_uri, bool use_secure_uri) {
     _print_job_t *print_job = IMPL(_print_job_t, ifc, this_p);
 
     if (!print_job) return ERROR;
diff --git a/jni/lib/wprintJNI.c b/jni/lib/wprintJNI.c
index 1dbddb8..913198a 100644
--- a/jni/lib/wprintJNI.c
+++ b/jni/lib/wprintJNI.c
@@ -1227,7 +1227,7 @@
  */
 JNIEXPORT jint JNICALL 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) {
+        jobject printerCaps, jobject fileArray, jstring jobDebugDir, jstring scheme) {
     LOGI("nativeStartJob, JNIenv is %p", env);
     jint result = ERROR;
     wJob_t job_handle = ERROR;
@@ -1245,6 +1245,7 @@
     const char *addressStr = (*env)->GetStringUTFChars(env, address, NULL);
     const char *mimeTypeStr = (*env)->GetStringUTFChars(env, mimeType, NULL);
     const char *dataDirStr = (*env)->GetStringUTFChars(env, _fakeDir, NULL);
+    const char *schemeStr = (*env)->GetStringUTFChars(env, scheme, NULL);
 
     jsize len = 0;
     jobjectArray array;
@@ -1309,7 +1310,7 @@
             jobDebugDirStr = (*env)->GetStringUTFChars(env, jobDebugDir, NULL);
         }
         result = wprintStartJob(addressStr, port, &params, &caps, (char *) mimeTypeStr,
-                (char *) dataDirStr, _wprint_callback_fn, jobDebugDirStr);
+                (char *) dataDirStr, _wprint_callback_fn, jobDebugDirStr, schemeStr);
         if (result == ERROR) {
             LOGE("failed to start job: error code :%d", errno);
         }
@@ -1362,6 +1363,7 @@
     (*env)->ReleaseStringUTFChars(env, mimeType, mimeTypeStr);
     (*env)->ReleaseStringUTFChars(env, address, addressStr);
     (*env)->ReleaseStringUTFChars(env, _fakeDir, dataDirStr);
+    (*env)->ReleaseStringUTFChars(env, scheme, schemeStr);
     return job_handle;
 }
 
diff --git a/src/com/android/bips/discovery/MdnsDiscovery.java b/src/com/android/bips/discovery/MdnsDiscovery.java
index fddffed..cfb334c 100644
--- a/src/com/android/bips/discovery/MdnsDiscovery.java
+++ b/src/com/android/bips/discovery/MdnsDiscovery.java
@@ -28,8 +28,11 @@
 import com.android.bips.BuiltInPrintService;
 
 import java.net.Inet4Address;
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
 
 /**
  * Search the local network for devices advertising IPP print services
@@ -37,6 +40,7 @@
 public class MdnsDiscovery extends Discovery {
     private static final String TAG = MdnsDiscovery.class.getSimpleName();
     private static final boolean DEBUG = false;
+    private static final long IPPS_DELAY = 150;
 
     // Prepend this to a UUID to create a proper URN
     private static final String PREFIX_URN_UUID = "urn:uuid:";
@@ -49,7 +53,11 @@
     private static final String VALUE_PRINT_WFDS_OPT_OUT = "F";
 
     // Service name of interest
-    private static final String SERVICE_IPP = "_ipp._tcp";
+    private static final String SERVICE_IPP =  "_ipp._tcp";
+    private static final String SERVICE_IPPS = "_ipps._tcp";
+
+    private static final String SCHEME_IPP = "ipp";
+    private static final String SCHEME_IPPS = "ipps";
 
     /** Network Service Discovery Manager */
     private final NsdManager mNsdManager;
@@ -58,7 +66,10 @@
     private final Handler mMainHandler;
 
     /** Handle to listener when registered */
-    private NsdServiceListener mServiceListener;
+    private NsdServiceListener mIppServiceListener;
+    private NsdServiceListener mIppsServiceListener;
+
+    private Map<Uri, IppsDelay> mIppsDelays = new HashMap<>();
 
     public MdnsDiscovery(BuiltInPrintService printService) {
         this(printService, (NsdManager) printService.getSystemService(Context.NSD_SERVICE));
@@ -102,8 +113,9 @@
             return null;
         }
 
-        Uri path = Uri.parse("ipp://" + info.getHost().getHostAddress() +
-                ":" + info.getPort() + "/" + resourcePath);
+        String scheme = info.getServiceType().contains(SERVICE_IPPS) ? SCHEME_IPPS : SCHEME_IPP;
+        Uri path = Uri.parse(scheme + "://" + info.getHost().getHostAddress() + ":" + info.getPort() + "/" +
+                resourcePath);
         String location = getStringAttribute(info, ATTRIBUTE_NOTE);
 
         return new DiscoveredPrinter(uuidUri, info.getServiceName(), path, location);
@@ -123,18 +135,44 @@
     @Override
     void onStart() {
         if (DEBUG) Log.d(TAG, "onStart()");
-        mServiceListener = new NsdServiceListener();
-        mNsdManager.discoverServices(SERVICE_IPP, NsdManager.PROTOCOL_DNS_SD, mServiceListener);
+        mIppServiceListener = new NsdServiceListener() {
+            @Override
+            public void onStartDiscoveryFailed(String s, int i) {
+                mIppServiceListener = null;
+            }
+        };
+
+        mNsdManager.discoverServices(SERVICE_IPP, NsdManager.PROTOCOL_DNS_SD, mIppServiceListener);
+
+        mIppsServiceListener = new NsdServiceListener() {
+            @Override
+            public void onStartDiscoveryFailed(String s, int i) {
+                mIppServiceListener = null;
+            }
+        };
+        mNsdManager.discoverServices(SERVICE_IPPS, NsdManager.PROTOCOL_DNS_SD, mIppsServiceListener);
     }
 
     @Override
     void onStop() {
         if (DEBUG) Log.d(TAG, "onStop()");
 
-        if (mServiceListener != null) {
-            mNsdManager.stopServiceDiscovery(mServiceListener);
-            mServiceListener = null;
+        NsdResolveQueue.getInstance(getPrintService()).clear();
+        for (IppsDelay ippsDelay : mIppsDelays.values()) {
+            mMainHandler.removeCallbacks(ippsDelay);
         }
+        mIppsDelays.clear();
+
+        if (mIppServiceListener != null) {
+            mNsdManager.stopServiceDiscovery(mIppServiceListener);
+            mIppServiceListener = null;
+        }
+
+        if (mIppsServiceListener != null) {
+            mNsdManager.stopServiceDiscovery(mIppsServiceListener);
+            mIppsServiceListener = null;
+        }
+
         mMainHandler.removeCallbacksAndMessages(null);
         NsdResolveQueue.getInstance(getPrintService()).clear();
     }
@@ -142,13 +180,8 @@
     /**
      * Manage notifications from NsdManager
      */
-    private class NsdServiceListener implements NsdManager.DiscoveryListener,
+    private abstract class NsdServiceListener implements NsdManager.DiscoveryListener,
             NsdManager.ResolveListener {
-        @Override
-        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
-            Log.w(TAG, "onStartDiscoveryFailed: " + errorCode);
-            mServiceListener = null;
-        }
 
         @Override
         public void onStopDiscoveryFailed(String s, int errorCode) {
@@ -182,6 +215,7 @@
             mMainHandler.post(() -> {
                 for (DiscoveredPrinter printer : getPrinters()) {
                     if (TextUtils.equals(printer.name, info.getServiceName())) {
+                        cancelIppsDelay(printer.getUri());
                         printerLost(printer.getUri());
                         return;
                     }
@@ -201,7 +235,41 @@
                 return;
             }
 
+            Uri printerUri = printer.getUri();
+            if (printer.path.getScheme().equals(SCHEME_IPPS)) {
+                DiscoveredPrinter oldPrinter = getPrinter(printerUri);
+                IppsDelay ippsDelay = mIppsDelays.get(printerUri);
+                if (oldPrinter == null && ippsDelay == null) {
+                    // This IPPS printer is not known yet so delay a short time to see if IPP arrives
+                    mIppsDelays.put(printerUri, new IppsDelay(printer));
+                }
+                return;
+            } else {
+                // IPP discovered, so cancel any outstanding IPPS delay
+                cancelIppsDelay(printerUri);
+            }
+
             mMainHandler.post(() -> printerFound(printer));
         }
     }
-}
\ No newline at end of file
+
+    private void cancelIppsDelay(Uri printerUri) {
+        IppsDelay ippsDelay = mIppsDelays.get(printerUri);
+        mMainHandler.removeCallbacks(ippsDelay);
+        mIppsDelays.remove(printerUri);
+    }
+
+    private class IppsDelay implements Runnable {
+        final DiscoveredPrinter printer;
+
+        IppsDelay(DiscoveredPrinter printer) {
+            this.printer = printer;
+            mMainHandler.postDelayed(this, IPPS_DELAY);
+        }
+
+        @Override
+        public void run() {
+            printerFound(printer);
+        }
+    }
+}
diff --git a/src/com/android/bips/ipp/Backend.java b/src/com/android/bips/ipp/Backend.java
index ef0c722..d089012 100644
--- a/src/com/android/bips/ipp/Backend.java
+++ b/src/com/android/bips/ipp/Backend.java
@@ -301,10 +301,11 @@
      * @param capabilities printer capabilities for the printer being used
      * @param fileList list of files to be provided of the given MIME type
      * @param debugDir directory to receive debugging information, if any
+     * @param scheme URI scheme (e.g. ipp/ipps)
      * @return {@link BackendConstants#STATUS_OK} or an error code.
      */
     native int nativeStartJob(String address, int port, String mime_type, LocalJobParams jobParams,
-            LocalPrinterCapabilities capabilities, String[] fileList, String debugDir);
+            LocalPrinterCapabilities capabilities, String[] fileList, String debugDir, String scheme);
 
     /**
      * Request cancellation of the identified job.
diff --git a/src/com/android/bips/ipp/StartJobTask.java b/src/com/android/bips/ipp/StartJobTask.java
index 1e1355b..0cbfa3f 100644
--- a/src/com/android/bips/ipp/StartJobTask.java
+++ b/src/com/android/bips/ipp/StartJobTask.java
@@ -167,7 +167,7 @@
             }
             // Initiate job
             result = mBackend.nativeStartJob(Backend.getIp(address), mDestination.getPort(),
-                    MIME_TYPE_PDF, mJobParams, mCapabilities, files, null);
+                    MIME_TYPE_PDF, mJobParams, mCapabilities, files, null, mDestination.getScheme());
             if (result < 0) {
                 Log.w(TAG, "nativeStartJob failure: " + result);
                 return Backend.ERROR_UNKNOWN;