summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-01-20 06:04:25 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-01-20 06:04:25 +0000
commitb8acc5fdacb470100f1f66b530cc4e399723a725 (patch)
tree55c181aab2781a109c10b26916a1e6975f9560dc
parentd123b55e609eb4b6732f59c94ea79210dc3ec10d (diff)
parent1e326d3a8ef665536a542f0ed64112dbe00a03c6 (diff)
downloadBuiltInPrintService-o-mr1-iot-preview-7.tar.gz
-rw-r--r--src/com/android/bips/discovery/ManualDiscovery.java89
-rw-r--r--src/com/android/bips/ipp/Backend.java8
-rw-r--r--src/com/android/bips/ipp/CapabilitiesCache.java4
-rw-r--r--src/com/android/bips/ipp/GetCapabilitiesTask.java19
-rw-r--r--src/com/android/bips/ui/AddManualPrinterDialog.java73
-rw-r--r--src/com/android/bips/ui/AddPrintersFragment.java2
6 files changed, 142 insertions, 53 deletions
diff --git a/src/com/android/bips/discovery/ManualDiscovery.java b/src/com/android/bips/discovery/ManualDiscovery.java
index 083844c..4b8f9a1 100644
--- a/src/com/android/bips/discovery/ManualDiscovery.java
+++ b/src/com/android/bips/discovery/ManualDiscovery.java
@@ -27,7 +27,10 @@ import com.android.bips.jni.LocalPrinterCapabilities;
import com.android.bips.util.WifiMonitor;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
/**
* Manage a list of printers manually added by the user.
@@ -37,12 +40,15 @@ public class ManualDiscovery extends SavedDiscovery {
private static final boolean DEBUG = false;
// Likely paths at which a print service may be found
- private static final Uri[] IPP_URIS = {Uri.parse("ipp://path:631/ipp/print"),
- Uri.parse("ipp://path:80/ipp/print"), Uri.parse("ipp://path:631/ipp/printer"),
- Uri.parse("ipp://path:631/ipp"), Uri.parse("ipp://path:631/")};
+ private static final Uri[] IPP_URIS = {Uri.parse("ipp://host:631/ipp/print"),
+ Uri.parse("ipp://host:80/ipp/print"), Uri.parse("ipp://host:631/ipp/printer"),
+ Uri.parse("ipp://host:631/ipp"), Uri.parse("ipp://host:631/"),
+ Uri.parse("ipps://host:631/ipp/print"), Uri.parse("ipps://host:443/ipp/print"),
+ Uri.parse("ipps://host:10443/ipp/print")};
private WifiMonitor mWifiMonitor;
private CapabilitiesCache mCapabilitiesCache;
+ private List<CapabilitiesFinder> mAddRequests = new ArrayList<>();
public ManualDiscovery(BuiltInPrintService printService) {
super(printService);
@@ -77,11 +83,54 @@ public class ManualDiscovery extends SavedDiscovery {
}
/**
- * Asynchronously attempt to add a new manual printer, calling back with success
+ * Asynchronously attempt to add a new manual printer, calling back with success if
+ * printer capabilities were discovered.
+ *
+ * The supplied URI must include a hostname and may also include a scheme (either ipp:// or
+ * ipps://), a port (such as :443), and/or a path (like /ipp/print). If any parts are missing,
+ * typical known values are substituted and searched until success is found, or all are
+ * tried unsuccessfully.
+ *
+ * @param printerUri URI to search
*/
- public void addManualPrinter(String hostname, PrinterAddCallback callback) {
- if (DEBUG) Log.d(TAG, "addManualPrinter " + hostname);
- new CapabilitiesFinder(hostname, callback);
+ public void addManualPrinter(Uri printerUri, PrinterAddCallback callback) {
+ if (DEBUG) Log.d(TAG, "addManualPrinter " + printerUri);
+
+ int givenPort = printerUri.getPort();
+ String givenPath = printerUri.getPath();
+ String hostname = printerUri.getHost();
+ String givenScheme = printerUri.getScheme();
+
+ // Use LinkedHashSet to eliminate duplicates but maintain order
+ Set<Uri> uris = new LinkedHashSet<>();
+ for (Uri uri : IPP_URIS) {
+ String scheme = uri.getScheme();
+ if (!TextUtils.isEmpty(givenScheme) && !scheme.equals(givenScheme)) {
+ // If scheme was supplied and doesn't match this uri template, skip
+ continue;
+ }
+ String authority = hostname + ":" + (givenPort == -1 ? uri.getPort() : givenPort);
+ String path = TextUtils.isEmpty(givenPath) ? uri.getPath() : givenPath;
+ Uri targetUri = uri.buildUpon().scheme(scheme).encodedAuthority(authority).path(path)
+ .build();
+ uris.add(targetUri);
+ }
+
+ mAddRequests.add(new CapabilitiesFinder(uris, callback));
+ }
+
+ /**
+ * Cancel a prior {@link #addManualPrinter(Uri, PrinterAddCallback)} attempt having the same
+ * callback
+ */
+ public void cancelAddManualPrinter(PrinterAddCallback callback) {
+ for (CapabilitiesFinder finder : mAddRequests) {
+ if (finder.mFinalCallback == callback) {
+ mAddRequests.remove(finder);
+ finder.cancel();
+ return;
+ }
+ }
}
/** Used to convey response to {@link #addManualPrinter} */
@@ -113,27 +162,26 @@ public class ManualDiscovery extends SavedDiscovery {
/**
* Constructs a new finder
*
- * @param hostname Hostname to crawl for IPP endpoints
+ * @param uris Locations to check for IPP endpoints
* @param callback Callback to issue when the first successful response arrives, or
* when all responses have failed.
*/
- CapabilitiesFinder(String hostname, PrinterAddCallback callback) {
+ CapabilitiesFinder(Collection<Uri> uris, PrinterAddCallback callback) {
mFinalCallback = callback;
-
- for (Uri uri : IPP_URIS) {
- Uri printerPath = uri.buildUpon().encodedAuthority(hostname + ":" + uri.getPort())
- .build();
+ for (Uri uri : uris) {
CapabilitiesCache.OnLocalPrinterCapabilities capabilitiesCallback =
new CapabilitiesCache.OnLocalPrinterCapabilities() {
@Override
public void onCapabilities(LocalPrinterCapabilities capabilities) {
mRequests.remove(this);
- handleCapabilities(printerPath, capabilities);
+ handleCapabilities(uri, capabilities);
}
};
mRequests.add(capabilitiesCallback);
- mCapabilitiesCache.request(new DiscoveredPrinter(null, "", printerPath, null),
+ // Force a clean attempt from scratch
+ mCapabilitiesCache.remove(uri);
+ mCapabilitiesCache.request(new DiscoveredPrinter(null, "", uri, null),
true, capabilitiesCallback);
}
}
@@ -144,6 +192,7 @@ public class ManualDiscovery extends SavedDiscovery {
if (capabilities == null) {
if (mRequests.isEmpty()) {
+ mAddRequests.remove(this);
mFinalCallback.onNotFound();
}
return;
@@ -169,8 +218,16 @@ public class ManualDiscovery extends SavedDiscovery {
printerFound(resolvedPrinter);
}
}
-
+ mAddRequests.remove(this);
mFinalCallback.onFound(resolvedPrinter, capabilities.isSupported);
}
+
+ /** Stop all in-progress capability requests that are in progress */
+ public void cancel() {
+ for (CapabilitiesCache.OnLocalPrinterCapabilities callback : mRequests) {
+ mCapabilitiesCache.cancel(callback);
+ }
+ mRequests.clear();
+ }
}
}
diff --git a/src/com/android/bips/ipp/Backend.java b/src/com/android/bips/ipp/Backend.java
index b3eed0f..94d6a11 100644
--- a/src/com/android/bips/ipp/Backend.java
+++ b/src/com/android/bips/ipp/Backend.java
@@ -89,16 +89,18 @@ public class Backend implements JobCallback {
}
/** Asynchronously get printer capabilities, returning results or null to a callback */
- public AsyncTask<?, ?, ?> getCapabilities(Uri uri, long timeout, boolean highPriority,
+ public GetCapabilitiesTask getCapabilities(Uri uri, long timeout, boolean highPriority,
final Consumer<LocalPrinterCapabilities> capabilitiesConsumer) {
if (DEBUG) Log.d(TAG, "getCapabilities()");
- return new GetCapabilitiesTask(this, uri, timeout, highPriority) {
+ GetCapabilitiesTask task = new GetCapabilitiesTask(this, uri, timeout, highPriority) {
@Override
protected void onPostExecute(LocalPrinterCapabilities result) {
capabilitiesConsumer.accept(result);
}
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ };
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return task;
}
/**
diff --git a/src/com/android/bips/ipp/CapabilitiesCache.java b/src/com/android/bips/ipp/CapabilitiesCache.java
index 6f51dee..dd4d258 100644
--- a/src/com/android/bips/ipp/CapabilitiesCache.java
+++ b/src/com/android/bips/ipp/CapabilitiesCache.java
@@ -230,7 +230,7 @@ public class CapabilitiesCache extends LruCache<Uri, LocalPrinterCapabilities> i
public class Request implements Consumer<LocalPrinterCapabilities> {
final DiscoveredPrinter mPrinter;
final List<OnLocalPrinterCapabilities> mCallbacks = new ArrayList<>();
- AsyncTask<?, ?, ?> mQuery;
+ GetCapabilitiesTask mQuery;
boolean mHighPriority = false;
long mTimeout;
@@ -245,7 +245,7 @@ public class CapabilitiesCache extends LruCache<Uri, LocalPrinterCapabilities> i
private void cancel() {
if (mQuery != null) {
- mQuery.cancel(true);
+ mQuery.forceCancel();
mQuery = null;
}
}
diff --git a/src/com/android/bips/ipp/GetCapabilitiesTask.java b/src/com/android/bips/ipp/GetCapabilitiesTask.java
index 762390e..987e917 100644
--- a/src/com/android/bips/ipp/GetCapabilitiesTask.java
+++ b/src/com/android/bips/ipp/GetCapabilitiesTask.java
@@ -32,7 +32,7 @@ import java.net.Socket;
import java.net.UnknownHostException;
/** A background task that queries a specific URI for its complete capabilities */
-class GetCapabilitiesTask extends AsyncTask<Void, Void, LocalPrinterCapabilities> {
+public class GetCapabilitiesTask extends AsyncTask<Void, Void, LocalPrinterCapabilities> {
private static final String TAG = GetCapabilitiesTask.class.getSimpleName();
private static final boolean DEBUG = false;
@@ -43,6 +43,7 @@ class GetCapabilitiesTask extends AsyncTask<Void, Void, LocalPrinterCapabilities
private final Uri mUri;
private final long mTimeout;
private final boolean mPriority;
+ private volatile Socket mSocket;
GetCapabilitiesTask(Backend backend, Uri uri, long timeout, boolean priority) {
mUri = uri;
@@ -53,11 +54,27 @@ class GetCapabilitiesTask extends AsyncTask<Void, Void, LocalPrinterCapabilities
private boolean isDeviceOnline(Uri uri) {
try (Socket socket = new Socket()) {
+ mSocket = socket;
InetSocketAddress a = new InetSocketAddress(uri.getHost(), uri.getPort());
socket.connect(a, (int) mTimeout);
return true;
} catch (IOException e) {
return false;
+ } finally {
+ mSocket = null;
+ }
+ }
+
+ /** Forcibly cancel this task, including stopping any socket that was opened */
+ public void forceCancel() {
+ cancel(true);
+ Socket socket = mSocket;
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ // Ignored
+ }
}
}
diff --git a/src/com/android/bips/ui/AddManualPrinterDialog.java b/src/com/android/bips/ui/AddManualPrinterDialog.java
index 5699b15..a46f5fd 100644
--- a/src/com/android/bips/ui/AddManualPrinterDialog.java
+++ b/src/com/android/bips/ui/AddManualPrinterDialog.java
@@ -21,6 +21,7 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
+import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@@ -46,18 +47,17 @@ import java.util.regex.Pattern;
* Allows the user to enter printer address manually
*/
class AddManualPrinterDialog extends AlertDialog implements TextWatcher,
- TextView.OnEditorActionListener, View.OnKeyListener {
+ TextView.OnEditorActionListener, View.OnKeyListener, ManualDiscovery.PrinterAddCallback {
private static final String TAG = AddManualPrinterDialog.class.getSimpleName();
private static final boolean DEBUG = false;
/**
- * A regex that matches IP addresses and domain names like "192.168.1.101" and
- * "printer1.company.com"
+ * A regex matching any printer URI with optional protocol, port and path.
*/
- private static final String NAME_IP_REGEX =
- "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*";
- private static final String HOSTNAME_REGEXP = "^" + NAME_IP_REGEX + "$";
- private static final Pattern HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
+ private static final String URI_REGEX =
+ "(ipp[s]?://)?[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*(:[0-9]+)?(/.*)?";
+ private static final String FULL_URI_REGEX = "^" + URI_REGEX + "$";
+ private static final Pattern FULL_URI_PATTERN = Pattern.compile(FULL_URI_REGEX);
private final ManualDiscovery mDiscovery;
private final Activity mActivity;
@@ -85,8 +85,8 @@ class AddManualPrinterDialog extends AlertDialog implements TextWatcher,
super.onCreate(savedInstanceState);
mAddButton = getButton(AlertDialog.BUTTON_POSITIVE);
- mHostnameView = (TextView) findViewById(R.id.hostname);
- mProgressBar = (ProgressBar) findViewById(R.id.progress);
+ mHostnameView = findViewById(R.id.hostname);
+ mProgressBar = findViewById(R.id.progress);
mAddButton.setOnClickListener(view1 -> addPrinter());
@@ -101,6 +101,13 @@ class AddManualPrinterDialog extends AlertDialog implements TextWatcher,
updateButtonState();
}
+ @Override
+ protected void onStop() {
+ if (DEBUG) Log.d(TAG, "onStop()");
+ super.onStop();
+ mDiscovery.cancelAddManualPrinter(this);
+ }
+
private void openKeyboard(TextView view) {
Window window = getWindow();
if (window != null) {
@@ -115,9 +122,8 @@ class AddManualPrinterDialog extends AlertDialog implements TextWatcher,
private void updateButtonState() {
String hostname = mHostnameView.getText().toString();
- Matcher hostMatch = HOSTNAME_PATTERN.matcher(hostname);
-
- mAddButton.setEnabled(hostMatch.matches());
+ Matcher uriMatcher = FULL_URI_PATTERN.matcher(hostname);
+ mAddButton.setEnabled(uriMatcher.matches());
}
/** Attempt to add the printer based on current data */
@@ -128,24 +134,31 @@ class AddManualPrinterDialog extends AlertDialog implements TextWatcher,
mProgressBar.setVisibility(View.VISIBLE);
// Begin an attempt to add the printer
- mDiscovery.addManualPrinter(mHostnameView.getText().toString(),
- new ManualDiscovery.PrinterAddCallback() {
- @Override
- public void onFound(DiscoveredPrinter printer, boolean supported) {
- if (supported) {
- // Success case
- dismiss();
- mActivity.finish();
- } else {
- error(getContext().getString(R.string.printer_not_supported));
- }
- }
-
- @Override
- public void onNotFound() {
- error(getContext().getString(R.string.no_printer_found));
- }
- });
+ String uriString = mHostnameView.getText().toString();
+ Uri printerUri;
+ if (uriString.contains("://")) {
+ printerUri = Uri.parse(uriString);
+ } else {
+ // create a schemeless URI
+ printerUri = Uri.parse("://" + uriString);
+ }
+ mDiscovery.addManualPrinter(printerUri, this);
+ }
+
+ @Override
+ public void onFound(DiscoveredPrinter printer, boolean supported) {
+ if (supported) {
+ // Success case
+ dismiss();
+ mActivity.finish();
+ } else {
+ error(getContext().getString(R.string.printer_not_supported));
+ }
+ }
+
+ @Override
+ public void onNotFound() {
+ error(getContext().getString(R.string.no_printer_found));
}
/** Inform user of error and allow them to correct it */
diff --git a/src/com/android/bips/ui/AddPrintersFragment.java b/src/com/android/bips/ui/AddPrintersFragment.java
index dc7b73e..7b51447 100644
--- a/src/com/android/bips/ui/AddPrintersFragment.java
+++ b/src/com/android/bips/ui/AddPrintersFragment.java
@@ -143,7 +143,7 @@ public class AddPrintersFragment extends PreferenceFragment implements ServiceCo
if (P2pUtils.isP2p(printer)) {
message = mPrintService.getString(R.string.connects_via_wifi_direct);
} else {
- message = mPrintService.getString(R.string.connects_via_network, printer.getHost());
+ message = mPrintService.getString(R.string.connects_via_network, printer.path);
}
new AlertDialog.Builder(getContext())
.setTitle(printer.name)