1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bips;
18 
19 import android.print.PrinterId;
20 import android.printservice.PrintService;
21 import android.util.JsonReader;
22 import android.util.JsonWriter;
23 import android.util.Log;
24 
25 import java.io.File;
26 import java.io.FileReader;
27 import java.io.FileWriter;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  * Persistent information about discovery sessions
34  */
35 class LocalDiscoverySessionInfo {
36     private static final String TAG = LocalDiscoverySessionInfo.class.getSimpleName();
37     private static final boolean DEBUG = false;
38 
39     private static final String CACHE_FILE = TAG + ".json";
40     private static final String NAME_KNOWN_GOOD = "knownGood";
41     private static final String NAME_PRIORITY = "priority";
42 
43     private static final int KNOWN_GOOD_MAX = 50;
44 
45     private final PrintService mService;
46     private final File mCacheFile;
47     private final List<PrinterId> mKnownGood = new ArrayList<>();
48     private List<PrinterId> mPriority = new ArrayList<>();
49 
LocalDiscoverySessionInfo(PrintService service)50     LocalDiscoverySessionInfo(PrintService service) {
51         mService = service;
52         mCacheFile = new File(service.getCacheDir(), CACHE_FILE);
53         load();
54     }
55 
56     /**
57      * Load cached info from storage, if possible
58      */
load()59     private void load() {
60         if (!mCacheFile.exists()) {
61             return;
62         }
63         try (JsonReader reader = new JsonReader(new FileReader(mCacheFile))) {
64             reader.beginObject();
65             while (reader.hasNext()) {
66                 switch (reader.nextName()) {
67                     case NAME_KNOWN_GOOD:
68                         mKnownGood.addAll(loadPrinterIds(reader));
69                         break;
70                     case NAME_PRIORITY:
71                         mPriority.addAll(loadPrinterIds(reader));
72                         break;
73                     default:
74                         reader.skipValue();
75                         break;
76                 }
77             }
78             reader.endObject();
79         } catch (IOException e) {
80             Log.w(TAG, "Failed to read info from " + CACHE_FILE, e);
81         }
82     }
83 
loadPrinterIds(JsonReader reader)84     private List<PrinterId> loadPrinterIds(JsonReader reader) throws IOException {
85         List<PrinterId> list = new ArrayList<>();
86         reader.beginArray();
87         while (reader.hasNext()) {
88             String localId = reader.nextString();
89             list.add(mService.generatePrinterId(localId));
90         }
91         reader.endArray();
92         return list;
93     }
94 
95     /**
96      * Save cached info to storage, if possible
97      */
save()98     void save() {
99         try (JsonWriter writer = new JsonWriter(new FileWriter(mCacheFile))) {
100             writer.beginObject();
101 
102             writer.name(NAME_KNOWN_GOOD);
103             savePrinterIds(writer, mKnownGood, KNOWN_GOOD_MAX);
104 
105             writer.name(NAME_PRIORITY);
106             savePrinterIds(writer, mPriority, mPriority.size());
107 
108             writer.endObject();
109         } catch (IOException e) {
110             Log.w(TAG, "Failed to write known good list", e);
111         }
112     }
113 
savePrinterIds(JsonWriter writer, List<PrinterId> ids, int max)114     private void savePrinterIds(JsonWriter writer, List<PrinterId> ids, int max)
115             throws IOException {
116         writer.beginArray();
117         int count = Math.min(max, ids.size());
118         for (int i = 0; i < count; i++) {
119             writer.value(ids.get(i).getLocalId());
120         }
121         writer.endArray();
122     }
123 
124     /**
125      * Return true if the ID indicates a printer with a successful capability request in the past
126      */
isKnownGood(PrinterId printerId)127     boolean isKnownGood(PrinterId printerId) {
128         return mKnownGood.contains(printerId);
129     }
130 
setKnownGood(PrinterId printerId)131     void setKnownGood(PrinterId printerId) {
132         mKnownGood.remove(printerId);
133         mKnownGood.add(0, printerId);
134     }
135 }
136