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 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 /** Return the address of the printer or {@code null} if not known */ 59 public InetAddress getAddress() { 60 if (mCapabilities != null) { 61 return mCapabilities.inetAddress; 62 } 63 return null; 64 } 65 66 /** Return true if this printer should be aged out */ 67 boolean isExpired() { 68 return !mFound && (System.currentTimeMillis() - mLastSeenTime) > 69 LocalDiscoverySession.PRINTER_EXPIRATION_MILLIS; 70 } 71 72 /** Return capabilities or null if not present */ 73 LocalPrinterCapabilities getCapabilities() { 74 return mCapabilities; 75 } 76 77 /** Create a PrinterInfo from this record or null if not possible */ 78 PrinterInfo createPrinterInfo() { 79 if (mCapabilities != null && !mCapabilities.isSupported) { 80 // Fail out if not supported. 81 return null; 82 } 83 84 // Get the most recently discovered version of this printer 85 DiscoveredPrinter printer = mPrintService.getDiscovery() 86 .getPrinter(mDiscoveredPrinter.getUri()); 87 if (printer == null) return null; 88 89 String description = printer.getDescription(mPrintService); 90 boolean idle = mFound && mCapabilities != null; 91 PrinterInfo.Builder builder = new PrinterInfo.Builder( 92 mPrinterId, printer.name, 93 idle ? PrinterInfo.STATUS_IDLE : PrinterInfo.STATUS_UNAVAILABLE) 94 .setIconResourceId(R.drawable.ic_printer) 95 .setDescription(description); 96 97 if (mCapabilities != null) { 98 // Add capabilities if we have them 99 PrinterCapabilitiesInfo.Builder capabilitiesBuilder = 100 new PrinterCapabilitiesInfo.Builder(mPrinterId); 101 mCapabilities.buildCapabilities(mPrintService, capabilitiesBuilder); 102 builder.setCapabilities(capabilitiesBuilder.build()); 103 } 104 105 return builder.build(); 106 } 107 108 @Override 109 public void onCapabilities(DiscoveredPrinter printer, LocalPrinterCapabilities capabilities) { 110 if (mSession.isDestroyed() || !mSession.isKnown(mPrinterId)) return; 111 112 if (capabilities == null) { 113 if (DEBUG) Log.d(TAG, "No capabilities so removing printer " + this); 114 mSession.removePrinters(Collections.singletonList(mPrinterId)); 115 } else { 116 mCapabilities = capabilities; 117 mSession.handlePrinter(this); 118 } 119 } 120 121 PrinterId getPrinterId() { 122 return mPrinterId; 123 } 124 125 /** Return true if the printer is in a "found" state according to discoveries */ 126 boolean isFound() { 127 return mFound; 128 } 129 130 /** Start a fresh request for capabilities */ 131 void requestCapabilities() { 132 mPrintService.getCapabilitiesCache().request(mDiscoveredPrinter, 133 mSession.isPriority(mPrinterId), this); 134 } 135 136 /** 137 * Indicate the printer was found and gather capabilities if we don't have them 138 */ 139 void found() { 140 mLastSeenTime = System.currentTimeMillis(); 141 mFound = true; 142 143 // Check for cached capabilities 144 Uri printerUri = mDiscoveredPrinter.getUri(); 145 LocalPrinterCapabilities capabilities = mPrintService.getCapabilitiesCache() 146 .get(printerUri); 147 if (DEBUG) Log.d(TAG, "Printer " + mDiscoveredPrinter + " has caps=" + capabilities); 148 149 if (capabilities != null) { 150 // Report current capabilities 151 onCapabilities(mDiscoveredPrinter, capabilities); 152 } else { 153 // Announce printer and fetch capabilities 154 mSession.handlePrinter(this); 155 requestCapabilities(); 156 } 157 } 158 159 /** 160 * Mark this printer as not found (will eventually expire) 161 */ 162 void notFound() { 163 mFound = false; 164 mLastSeenTime = System.currentTimeMillis(); 165 } 166 167 /** Return the UUID for this printer if it is known */ 168 public Uri getUuid() { 169 return mDiscoveredPrinter.uuid; 170 } 171 172 @Override 173 public String toString() { 174 return mDiscoveredPrinter.toString(); 175 } 176 }