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.discovery; 19 20 import android.net.Uri; 21 import android.util.Log; 22 23 import java.util.ArrayList; 24 import java.util.Arrays; 25 import java.util.Collection; 26 import java.util.List; 27 28 /** Combines the behavior of multiple child {@link Discovery} objects to a single one */ 29 public class MultiDiscovery extends Discovery { 30 private static final String TAG = MultiDiscovery.class.getSimpleName(); 31 private static final boolean DEBUG = false; 32 33 private final List<Discovery> mDiscoveries = new ArrayList<>(); 34 private final List<Discovery> mStartedDiscoveries = new ArrayList<>(); 35 private final Listener mChildListener; 36 37 /** 38 * Construct an aggregate discovery mechanism, with preferred discovery mechanisms first 39 */ MultiDiscovery(Discovery first, Discovery... rest)40 public MultiDiscovery(Discovery first, Discovery... rest) { 41 super(first.getPrintService()); 42 mDiscoveries.add(first); 43 mDiscoveries.addAll(Arrays.asList(rest)); 44 mChildListener = new Listener() { 45 @Override 46 public void onPrinterFound(DiscoveredPrinter printer) { 47 printerFound(merged(printer.getUri())); 48 } 49 50 @Override 51 public void onPrinterLost(DiscoveredPrinter printer) { 52 // Merge remaining printer records, if any 53 DiscoveredPrinter remaining = merged(printer.getUri()); 54 if (remaining == null) { 55 printerLost(printer.getUri()); 56 } else { 57 printerFound(remaining); 58 } 59 } 60 }; 61 } 62 63 /** 64 * For a given URI combine and return records with the same printerUri, based on discovery 65 * mechanism order. 66 */ merged(Uri printerUri)67 private DiscoveredPrinter merged(Uri printerUri) { 68 DiscoveredPrinter combined = null; 69 70 for (Discovery discovery : getChildren()) { 71 DiscoveredPrinter discovered = discovery.getPrinter(printerUri); 72 if (discovered != null) { 73 if (combined == null) { 74 combined = discovered; 75 } else { 76 // Merge all paths found, in order, without duplicates 77 List<Uri> allPaths = new ArrayList<>(combined.paths); 78 for (Uri path : discovered.paths) { 79 if (!allPaths.contains(path)) { 80 allPaths.add(path); 81 } 82 } 83 // Assemble a new printer containing paths. 84 combined = new DiscoveredPrinter(discovered.uuid, discovered.name, allPaths, 85 discovered.location); 86 } 87 } 88 } 89 90 return combined; 91 } 92 93 @Override onStart()94 void onStart() { 95 if (DEBUG) Log.d(TAG, "onStart()"); 96 for (Discovery discovery : mDiscoveries) { 97 discovery.start(mChildListener); 98 mStartedDiscoveries.add(discovery); 99 } 100 } 101 stopAndClearAll()102 private void stopAndClearAll() { 103 for (Discovery discovery : mStartedDiscoveries) { 104 discovery.stop(mChildListener); 105 } 106 mStartedDiscoveries.clear(); 107 allPrintersLost(); 108 } 109 110 @Override onStop()111 void onStop() { 112 if (DEBUG) Log.d(TAG, "onStop()"); 113 stopAndClearAll(); 114 } 115 116 @Override getChildren()117 Collection<Discovery> getChildren() { 118 List<Discovery> children = new ArrayList<>(); 119 for (Discovery child : mDiscoveries) { 120 children.addAll(child.getChildren()); 121 } 122 return children; 123 } 124 } 125