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; 19 20 import android.net.Uri; 21 import android.print.PrinterCapabilitiesInfo; 22 import android.print.PrinterId; 23 import android.print.PrinterInfo; 24 import android.util.Log; 25 26 import com.android.bips.discovery.DiscoveredPrinter; 27 import com.android.bips.ipp.CapabilitiesCache; 28 import com.android.bips.jni.LocalPrinterCapabilities; 29 30 import java.net.InetAddress; 31 import java.net.UnknownHostException; 32 import java.util.Collections; 33 34 /** 35 * A session-specific printer record. Encapsulates logic for getting the latest printer 36 * capabilities as necessary. 37 */ 38 class LocalPrinter implements CapabilitiesCache.OnLocalPrinterCapabilities { 39 private static final String TAG = LocalPrinter.class.getSimpleName(); 40 private static final boolean DEBUG = false; 41 42 private final BuiltInPrintService mPrintService; 43 private final DiscoveredPrinter mDiscoveredPrinter; 44 private final LocalDiscoverySession mSession; 45 private final PrinterId mPrinterId; 46 private long mLastSeenTime = System.currentTimeMillis(); 47 private boolean mFound = true; 48 private LocalPrinterCapabilities mCapabilities; 49 LocalPrinter(BuiltInPrintService printService, LocalDiscoverySession session, DiscoveredPrinter discoveredPrinter)50 LocalPrinter(BuiltInPrintService printService, LocalDiscoverySession session, 51 DiscoveredPrinter discoveredPrinter) { 52 mPrintService = printService; 53 mSession = session; 54 mDiscoveredPrinter = discoveredPrinter; 55 mPrinterId = discoveredPrinter.getId(printService); 56 } 57 58 /** 59 * @return The address of the printer or {@code null} if the printer is not reachable 60 * 61 * @throws UnknownHostException if the address could not be resolved 62 */ getAddress()63 public InetAddress getAddress() throws UnknownHostException { 64 return InetAddress.getByName(mDiscoveredPrinter.path.getHost()); 65 } 66 67 /** Return true if this printer should be aged out */ isExpired()68 boolean isExpired() { 69 return !mFound && (System.currentTimeMillis() - mLastSeenTime) > 70 LocalDiscoverySession.PRINTER_EXPIRATION_MILLIS; 71 } 72 73 /** Return capabilities or null if not present */ getCapabilities()74 LocalPrinterCapabilities getCapabilities() { 75 return mCapabilities; 76 } 77 78 /** Create a PrinterInfo from this record or null if not possible */ createPrinterInfo()79 PrinterInfo createPrinterInfo() { 80 if (mCapabilities != null && !mCapabilities.isSupported) { 81 // Fail out if not supported. 82 return null; 83 } 84 85 String description = mDiscoveredPrinter.getDescription(mPrintService); 86 boolean idle = mFound && mCapabilities != null; 87 PrinterInfo.Builder builder = new PrinterInfo.Builder( 88 mPrinterId, mDiscoveredPrinter.name, 89 idle ? PrinterInfo.STATUS_IDLE : PrinterInfo.STATUS_UNAVAILABLE) 90 .setIconResourceId(R.drawable.ic_printer) 91 .setDescription(description); 92 93 if (mCapabilities != null) { 94 // Add capabilities if we have them 95 PrinterCapabilitiesInfo.Builder capabilitiesBuilder = 96 new PrinterCapabilitiesInfo.Builder(mPrinterId); 97 mCapabilities.buildCapabilities(mPrintService, capabilitiesBuilder); 98 builder.setCapabilities(capabilitiesBuilder.build()); 99 } 100 101 return builder.build(); 102 } 103 104 @Override onCapabilities(LocalPrinterCapabilities capabilities)105 public void onCapabilities(LocalPrinterCapabilities capabilities) { 106 if (mSession.isDestroyed() || !mSession.isKnown(mPrinterId)) return; 107 108 if (capabilities == null) { 109 if (DEBUG) Log.d(TAG, "No capabilities so removing printer " + this); 110 mSession.removePrinters(Collections.singletonList(mPrinterId)); 111 } else { 112 mCapabilities = capabilities; 113 mSession.handlePrinter(this); 114 } 115 } 116 getPrinterId()117 PrinterId getPrinterId() { 118 return mPrinterId; 119 } 120 121 /** Return true if the printer is in a "found" state according to discoveries */ isFound()122 boolean isFound() { 123 return mFound; 124 } 125 126 /** Start a fresh request for capabilities */ requestCapabilities()127 void requestCapabilities() { 128 mPrintService.getCapabilitiesCache().request(mDiscoveredPrinter, 129 mSession.isPriority(mPrinterId), this); 130 } 131 132 /** 133 * Indicate the printer was found and gather capabilities if we don't have them 134 */ found()135 void found() { 136 mLastSeenTime = System.currentTimeMillis(); 137 mFound = true; 138 139 // Check for cached capabilities 140 Uri printerUri = mDiscoveredPrinter.getUri(); 141 LocalPrinterCapabilities capabilities = mPrintService.getCapabilitiesCache() 142 .get(printerUri); 143 if (DEBUG) Log.d(TAG, "Printer " + mDiscoveredPrinter + " has caps=" + capabilities); 144 145 if (capabilities != null) { 146 // Report current capabilities 147 onCapabilities(capabilities); 148 } else { 149 // Announce printer and fetch capabilities 150 mSession.handlePrinter(this); 151 requestCapabilities(); 152 } 153 } 154 155 /** 156 * Mark this printer as not found (will eventually expire) 157 */ notFound()158 void notFound() { 159 mFound = false; 160 mLastSeenTime = System.currentTimeMillis(); 161 } 162 163 /** Return the UUID for this printer if it is known */ getUuid()164 public Uri getUuid() { 165 return mDiscoveredPrinter.uuid; 166 } 167 168 @Override toString()169 public String toString() { 170 return mDiscoveredPrinter.toString(); 171 } 172 }