1 /*
2  * Copyright (C) 2014 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.printspooler.ui;
18 
19 import android.app.Activity;
20 import android.app.LoaderManager.LoaderCallbacks;
21 import android.content.Loader;
22 import android.os.Bundle;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.os.Message;
26 import android.print.PrinterId;
27 import android.print.PrinterInfo;
28 import com.android.internal.os.SomeArgs;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 public class PrinterRegistry {
34 
35     private static final int LOADER_ID_PRINTERS_LOADER = 1;
36 
37     private final Activity mActivity;
38 
39     private final List<PrinterInfo> mPrinters = new ArrayList<>();
40 
41     private final Runnable mReadyCallback;
42 
43     private final Handler mHandler;
44 
45     private boolean mReady;
46 
47     private OnPrintersChangeListener mOnPrintersChangeListener;
48 
49     public interface OnPrintersChangeListener {
onPrintersChanged(List<PrinterInfo> printers)50         public void onPrintersChanged(List<PrinterInfo> printers);
onPrintersInvalid()51         public void onPrintersInvalid();
52     }
53 
PrinterRegistry(Activity activity, Runnable readyCallback)54     public PrinterRegistry(Activity activity, Runnable readyCallback) {
55         mActivity = activity;
56         mReadyCallback = readyCallback;
57         mHandler = new MyHandler(activity.getMainLooper());
58         activity.getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER,
59                 null, mLoaderCallbacks);
60     }
61 
setOnPrintersChangeListener(OnPrintersChangeListener listener)62     public void setOnPrintersChangeListener(OnPrintersChangeListener listener) {
63         mOnPrintersChangeListener = listener;
64     }
65 
getPrinters()66     public List<PrinterInfo> getPrinters() {
67         return mPrinters;
68     }
69 
addHistoricalPrinter(PrinterInfo printer)70     public void addHistoricalPrinter(PrinterInfo printer) {
71         FusedPrintersProvider provider = getPrinterProvider();
72         if (provider != null) {
73             getPrinterProvider().addHistoricalPrinter(printer);
74         }
75     }
76 
forgetFavoritePrinter(PrinterId printerId)77     public void forgetFavoritePrinter(PrinterId printerId) {
78         FusedPrintersProvider provider = getPrinterProvider();
79         if (provider != null) {
80             provider.forgetFavoritePrinter(printerId);
81         }
82     }
83 
isFavoritePrinter(PrinterId printerId)84     public boolean isFavoritePrinter(PrinterId printerId) {
85         FusedPrintersProvider provider = getPrinterProvider();
86         if (provider != null) {
87             return provider.isFavoritePrinter(printerId);
88         }
89         return false;
90     }
91 
setTrackedPrinter(PrinterId printerId)92     public void setTrackedPrinter(PrinterId printerId) {
93         FusedPrintersProvider provider = getPrinterProvider();
94         if (provider != null) {
95             provider.setTrackedPrinter(printerId);
96         }
97     }
98 
areHistoricalPrintersLoaded()99     public boolean areHistoricalPrintersLoaded() {
100         FusedPrintersProvider provider = getPrinterProvider();
101         if (provider != null) {
102             return getPrinterProvider().areHistoricalPrintersLoaded();
103         }
104         return false;
105     }
106 
getPrinterProvider()107     private FusedPrintersProvider getPrinterProvider() {
108         Loader<?> loader = mActivity.getLoaderManager().getLoader(LOADER_ID_PRINTERS_LOADER);
109         return (FusedPrintersProvider) loader;
110     }
111 
112     private final LoaderCallbacks<List<PrinterInfo>> mLoaderCallbacks =
113             new LoaderCallbacks<List<PrinterInfo>>() {
114         @Override
115         public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
116             if (loader.getId() == LOADER_ID_PRINTERS_LOADER) {
117                 mPrinters.clear();
118                 if (mOnPrintersChangeListener != null) {
119                     // Post a message as we are in onLoadFinished and certain operations
120                     // are not allowed in this callback, such as fragment transactions.
121                     // Clients should not handle this explicitly.
122                     mHandler.obtainMessage(MyHandler.MSG_PRINTERS_INVALID,
123                             mOnPrintersChangeListener).sendToTarget();
124                 }
125             }
126         }
127 
128         // LoaderCallbacks#onLoadFinished
129         @Override
130         public void onLoadFinished(Loader<List<PrinterInfo>> loader, List<PrinterInfo> printers) {
131             if (loader.getId() == LOADER_ID_PRINTERS_LOADER) {
132                 mPrinters.clear();
133                 mPrinters.addAll(printers);
134                 if (mOnPrintersChangeListener != null) {
135                     // Post a message as we are in onLoadFinished and certain operations
136                     // are not allowed in this callback, such as fragment transactions.
137                     // Clients should not handle this explicitly.
138                     SomeArgs args = SomeArgs.obtain();
139                     args.arg1 = mOnPrintersChangeListener;
140                     args.arg2 = printers;
141                     mHandler.obtainMessage(MyHandler.MSG_PRINTERS_CHANGED, args).sendToTarget();
142                 }
143                 if (!mReady) {
144                     mReady = true;
145                     if (mReadyCallback != null) {
146                         mReadyCallback.run();
147                     }
148                 }
149             }
150         }
151 
152         // LoaderCallbacks#onCreateLoader
153         @Override
154         public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
155             if (id == LOADER_ID_PRINTERS_LOADER) {
156                 return new FusedPrintersProvider(mActivity);
157             }
158             return null;
159         }
160     };
161 
162     private static final class MyHandler extends Handler {
163         public static final int MSG_PRINTERS_CHANGED = 0;
164         public static final int MSG_PRINTERS_INVALID = 1;
165 
MyHandler(Looper looper)166         public MyHandler(Looper looper) {
167             super(looper, null , false);
168         }
169 
170         @Override
171         @SuppressWarnings("unchecked")
handleMessage(Message message)172         public void handleMessage(Message message) {
173             switch (message.what) {
174                 case MSG_PRINTERS_CHANGED: {
175                     SomeArgs args = (SomeArgs) message.obj;
176                     OnPrintersChangeListener callback = (OnPrintersChangeListener) args.arg1;
177                     List<PrinterInfo> printers = (List<PrinterInfo>) args.arg2;
178                     args.recycle();
179                     callback.onPrintersChanged(printers);
180                 } break;
181 
182                 case MSG_PRINTERS_INVALID: {
183                     OnPrintersChangeListener callback = (OnPrintersChangeListener) message.obj;
184                     callback.onPrintersInvalid();
185                 } break;
186             }
187         }
188     }
189 }
190