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