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 27 import java.io.IOException; 28 import java.net.InetAddress; 29 import java.net.InetSocketAddress; 30 import java.net.Socket; 31 import java.net.UnknownHostException; 32 import java.util.concurrent.locks.Lock; 33 import java.util.concurrent.locks.ReentrantLock; 34 35 /** A background task that queries a specific URI for its complete capabilities */ 36 class GetCapabilitiesTask extends AsyncTask<Void, Void, LocalPrinterCapabilities> { 37 private static final String TAG = GetCapabilitiesTask.class.getSimpleName(); 38 private static final boolean DEBUG = false; 39 40 /** Lock to ensure we don't issue multiple simultaneous capability requests */ 41 private static final Lock sJniLock = new ReentrantLock(); 42 43 private final Backend mBackend; 44 private final Uri mUri; 45 private final long mTimeout; 46 GetCapabilitiesTask(Backend backend, Uri uri, long timeout)47 GetCapabilitiesTask(Backend backend, Uri uri, long timeout) { 48 mUri = uri; 49 mBackend = backend; 50 mTimeout = timeout; 51 } 52 isDeviceOnline(Uri uri)53 private boolean isDeviceOnline(Uri uri) { 54 try (Socket socket = new Socket()) { 55 InetSocketAddress a = new InetSocketAddress(uri.getHost(), uri.getPort()); 56 socket.connect(a, (int) mTimeout); 57 return true; 58 } catch (IOException e) { 59 return false; 60 } 61 } 62 63 @Override doInBackground(Void... dummy)64 protected LocalPrinterCapabilities doInBackground(Void... dummy) { 65 long start = System.currentTimeMillis(); 66 67 LocalPrinterCapabilities printerCaps = new LocalPrinterCapabilities(); 68 try { 69 printerCaps.inetAddress = InetAddress.getByName(mUri.getHost()); 70 } catch (UnknownHostException e) { 71 return null; 72 } 73 74 boolean online = isDeviceOnline(mUri); 75 if (DEBUG) { 76 Log.d(TAG, "isDeviceOnline uri=" + mUri + " online=" + online + 77 " (" + (System.currentTimeMillis() - start) + "ms)"); 78 } 79 80 if (!online || isCancelled()) return null; 81 82 // Do not permit more than a single call to this API or crashes may result 83 sJniLock.lock(); 84 int status = -1; 85 start = System.currentTimeMillis(); 86 try { 87 if (isCancelled()) return null; 88 status = mBackend.nativeGetCapabilities(Backend.getIp(mUri.getHost()), 89 mUri.getPort(), mUri.getPath(), mUri.getScheme(), mTimeout, printerCaps); 90 } finally { 91 sJniLock.unlock(); 92 } 93 94 if (DEBUG) { 95 Log.d(TAG, "callNativeGetCapabilities uri=" + mUri + " status=" + status + 96 " (" + (System.currentTimeMillis() - start) + "ms)"); 97 } 98 99 return status == BackendConstants.STATUS_OK ? printerCaps : null; 100 } 101 }