blob: b8f3da65506e060636ef5c6b030d3b59acbc1f65 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.bips;
import android.net.Uri;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.util.Log;
import android.widget.Toast;
import com.android.bips.discovery.ConnectionListener;
import com.android.bips.discovery.DiscoveredPrinter;
import com.android.bips.ipp.CapabilitiesCache;
import com.android.bips.jni.LocalPrinterCapabilities;
import com.android.bips.p2p.P2pPrinterConnection;
import com.android.bips.p2p.P2pUtils;
import java.net.InetAddress;
import java.util.Collections;
/**
* A session-specific printer record. Encapsulates logic for getting the latest printer
* capabilities as necessary.
*/
class LocalPrinter implements CapabilitiesCache.OnLocalPrinterCapabilities {
private static final String TAG = LocalPrinter.class.getSimpleName();
private static final boolean DEBUG = false;
private final BuiltInPrintService mPrintService;
private final LocalDiscoverySession mSession;
private final PrinterId mPrinterId;
private long mLastSeenTime = System.currentTimeMillis();
private boolean mFound = true;
private boolean mTracking = false;
private LocalPrinterCapabilities mCapabilities;
private DiscoveredPrinter mDiscoveredPrinter;
private P2pPrinterConnection mTrackingConnection;
LocalPrinter(BuiltInPrintService printService, LocalDiscoverySession session,
DiscoveredPrinter discoveredPrinter) {
mPrintService = printService;
mSession = session;
mDiscoveredPrinter = discoveredPrinter;
mPrinterId = discoveredPrinter.getId(printService);
}
/** Return the address of the printer or {@code null} if not known */
public InetAddress getAddress() {
if (mCapabilities != null) {
return mCapabilities.inetAddress;
}
return null;
}
/** Return true if this printer should be aged out */
boolean isExpired() {
return !mFound && (System.currentTimeMillis() - mLastSeenTime)
> LocalDiscoverySession.PRINTER_EXPIRATION_MILLIS;
}
/** Return capabilities or null if not present */
LocalPrinterCapabilities getCapabilities() {
return mCapabilities;
}
/** Create a PrinterInfo from this record or null if not possible */
PrinterInfo createPrinterInfo(boolean knownGood) {
if (mCapabilities == null) {
if (P2pUtils.isP2p(mDiscoveredPrinter)) {
// Allow user to select a P2P to establish a connection
PrinterInfo.Builder builder = new PrinterInfo.Builder(
mPrinterId, mDiscoveredPrinter.name,
PrinterInfo.STATUS_IDLE)
.setIconResourceId(R.drawable.ic_printer)
.setDescription(mPrintService.getDescription(mDiscoveredPrinter));
return builder.build();
} else if (!knownGood) {
// Ignore unknown LAN printers with no caps
return null;
}
} else if (!mCapabilities.isSupported) {
// Fail out if capabilities indicate not-supported.
return null;
}
// Get the most recently discovered version of this printer
DiscoveredPrinter printer = mPrintService.getDiscovery()
.getPrinter(mDiscoveredPrinter.getUri());
if (printer == null) {
return null;
}
boolean idle = mFound && mCapabilities != null;
PrinterInfo.Builder builder = new PrinterInfo.Builder(
mPrinterId, printer.name,
idle ? PrinterInfo.STATUS_IDLE : PrinterInfo.STATUS_UNAVAILABLE)
.setIconResourceId(R.drawable.ic_printer)
.setDescription(mPrintService.getDescription(mDiscoveredPrinter));
if (mCapabilities != null) {
// Add capabilities if we have them
PrinterCapabilitiesInfo.Builder capabilitiesBuilder =
new PrinterCapabilitiesInfo.Builder(mPrinterId);
mCapabilities.buildCapabilities(mPrintService, capabilitiesBuilder);
builder.setCapabilities(capabilitiesBuilder.build());
}
return builder.build();
}
@Override
public void onCapabilities(LocalPrinterCapabilities capabilities) {
if (mSession.isDestroyed() || !mSession.isKnown(mPrinterId)) {
return;
}
if (capabilities == null) {
if (DEBUG) Log.d(TAG, "No capabilities so removing printer " + this);
mSession.removePrinters(Collections.singletonList(mPrinterId));
} else {
mCapabilities = capabilities;
mSession.handlePrinter(this);
}
}
PrinterId getPrinterId() {
return mPrinterId;
}
/** Return true if the printer is in a "found" state according to discoveries */
boolean isFound() {
return mFound;
}
/**
* Indicate the printer was found and gather capabilities if we don't have them
*/
void found(DiscoveredPrinter printer) {
mDiscoveredPrinter = printer;
mLastSeenTime = System.currentTimeMillis();
mFound = true;
// Check for cached capabilities
LocalPrinterCapabilities capabilities = mPrintService.getCapabilitiesCache()
.get(mDiscoveredPrinter);
if (capabilities != null) {
// Report current capabilities
onCapabilities(capabilities);
} else {
// Announce printer and fetch capabilities immediately if possible
mSession.handlePrinter(this);
if (!P2pUtils.isP2p(mDiscoveredPrinter)) {
mPrintService.getCapabilitiesCache().request(mDiscoveredPrinter,
mSession.isPriority(mPrinterId), this);
} else if (mTracking) {
startTracking();
}
}
}
/**
* Begin tracking (getting latest capabilities) for this printer
*/
public void track() {
if (DEBUG) Log.d(TAG, "track " + mDiscoveredPrinter);
startTracking();
}
private void startTracking() {
mTracking = true;
if (mTrackingConnection != null) {
return;
}
// For any P2P printer, obtain a connection
if (P2pUtils.isP2p(mDiscoveredPrinter)
|| P2pUtils.isOnConnectedInterface(mPrintService, mDiscoveredPrinter)) {
ConnectionListener listener = new ConnectionListener() {
@Override
public void onConnectionComplete(DiscoveredPrinter printer) {
if (DEBUG) Log.d(TAG, "connection complete " + printer);
if (printer == null) {
mTrackingConnection = null;
}
}
@Override
public void onConnectionDelayed(boolean delayed) {
if (DEBUG) Log.d(TAG, "connection delayed=" + delayed);
if (delayed) {
Toast.makeText(mPrintService, R.string.connect_hint_text,
Toast.LENGTH_LONG).show();
}
}
};
mTrackingConnection = new P2pPrinterConnection(mPrintService,
mDiscoveredPrinter, listener);
}
}
/**
* Stop tracking this printer
*/
void stopTracking() {
if (mTrackingConnection != null) {
mTrackingConnection.close();
mTrackingConnection = null;
}
mTracking = false;
}
/**
* Mark this printer as not found (will eventually expire)
*/
void notFound() {
mFound = false;
mLastSeenTime = System.currentTimeMillis();
}
/** Return the UUID for this printer if it is known */
public Uri getUuid() {
return mDiscoveredPrinter.uuid;
}
@Override
public String toString() {
return mDiscoveredPrinter.toString();
}
}