Home | History | Annotate | Download | only in ipp
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  * Copyright (C) 2016 Mopria Alliance, Inc.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.bips.ipp;
     19 
     20 import android.net.Uri;
     21 import android.os.AsyncTask;
     22 import android.util.Log;
     23 
     24 import com.android.bips.jni.BackendConstants;
     25 import com.android.bips.jni.LocalPrinterCapabilities;
     26 import com.android.bips.util.PriorityLock;
     27 
     28 import java.io.IOException;
     29 import java.net.InetAddress;
     30 import java.net.InetSocketAddress;
     31 import java.net.Socket;
     32 import java.net.UnknownHostException;
     33 
     34 /** A background task that queries a specific URI for its complete capabilities */
     35 public class GetCapabilitiesTask extends AsyncTask<Void, Void, LocalPrinterCapabilities> {
     36     private static final String TAG = GetCapabilitiesTask.class.getSimpleName();
     37     private static final boolean DEBUG = false;
     38 
     39     /** Lock to ensure we don't issue multiple simultaneous capability requests */
     40     private static final PriorityLock sLock = new PriorityLock();
     41 
     42     private final Backend mBackend;
     43     private final Uri mUri;
     44     private final long mTimeout;
     45     private final boolean mPriority;
     46     private volatile Socket mSocket;
     47 
     48     GetCapabilitiesTask(Backend backend, Uri uri, long timeout, boolean priority) {
     49         mUri = uri;
     50         mBackend = backend;
     51         mTimeout = timeout;
     52         mPriority = priority;
     53     }
     54 
     55     private boolean isDeviceOnline(Uri uri) {
     56         try (Socket socket = new Socket()) {
     57             mSocket = socket;
     58             InetSocketAddress a = new InetSocketAddress(uri.getHost(), uri.getPort());
     59             socket.connect(a, (int) mTimeout);
     60             return true;
     61         } catch (IOException e) {
     62             return false;
     63         } finally {
     64             mSocket = null;
     65         }
     66     }
     67 
     68     /** Forcibly cancel this task, including stopping any socket that was opened */
     69     public void forceCancel() {
     70         cancel(true);
     71         Socket socket = mSocket;
     72         if (socket != null) {
     73             try {
     74                 socket.close();
     75             } catch (IOException e) {
     76                 // Ignored
     77             }
     78         }
     79     }
     80 
     81     @Override
     82     protected LocalPrinterCapabilities doInBackground(Void... dummy) {
     83         long start = System.currentTimeMillis();
     84 
     85         LocalPrinterCapabilities printerCaps = new LocalPrinterCapabilities();
     86         try {
     87             printerCaps.inetAddress = InetAddress.getByName(mUri.getHost());
     88         } catch (UnknownHostException e) {
     89             return null;
     90         }
     91 
     92         boolean online = isDeviceOnline(mUri);
     93         if (DEBUG) {
     94             Log.d(TAG, "isDeviceOnline uri=" + mUri + " online=" + online
     95                     + " (" + (System.currentTimeMillis() - start) + "ms)");
     96         }
     97 
     98         if (!online || isCancelled()) {
     99             return null;
    100         }
    101 
    102         // Do not permit more than a single call to this API or crashes may result
    103         try {
    104             // Always allow priority capability requests to execute first
    105             sLock.lock(mPriority ? 1 : 0);
    106         } catch (InterruptedException e) {
    107             return null;
    108         }
    109         int status = -1;
    110         start = System.currentTimeMillis();
    111         try {
    112             if (isCancelled()) {
    113                 return null;
    114             }
    115             status = mBackend.nativeGetCapabilities(Backend.getIp(mUri.getHost()),
    116                     mUri.getPort(), mUri.getPath(), mUri.getScheme(), mTimeout, printerCaps);
    117         } finally {
    118             sLock.unlock();
    119         }
    120 
    121         if (DEBUG) {
    122             Log.d(TAG, "callNativeGetCapabilities uri=" + mUri + " status=" + status
    123                     + " (" + (System.currentTimeMillis() - start) + "ms)");
    124         }
    125 
    126         return status == BackendConstants.STATUS_OK ? printerCaps : null;
    127     }
    128 }
    129