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
17package com.android.printspooler.ui;
18
19import android.app.Activity;
20import android.app.LoaderManager.LoaderCallbacks;
21import android.content.Loader;
22import android.os.Bundle;
23import android.os.Handler;
24import android.os.Looper;
25import android.os.Message;
26import android.print.PrinterId;
27import android.print.PrinterInfo;
28import com.android.internal.os.SomeArgs;
29
30import java.util.ArrayList;
31import java.util.List;
32
33public 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 {
50        public void onPrintersChanged(List<PrinterInfo> printers);
51        public void onPrintersInvalid();
52    }
53
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
62    public void setOnPrintersChangeListener(OnPrintersChangeListener listener) {
63        mOnPrintersChangeListener = listener;
64    }
65
66    public List<PrinterInfo> getPrinters() {
67        return mPrinters;
68    }
69
70    public void addHistoricalPrinter(PrinterInfo printer) {
71        FusedPrintersProvider provider = getPrinterProvider();
72        if (provider != null) {
73            getPrinterProvider().addHistoricalPrinter(printer);
74        }
75    }
76
77    public void forgetFavoritePrinter(PrinterId printerId) {
78        FusedPrintersProvider provider = getPrinterProvider();
79        if (provider != null) {
80            provider.forgetFavoritePrinter(printerId);
81        }
82    }
83
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
92    public void setTrackedPrinter(PrinterId printerId) {
93        FusedPrintersProvider provider = getPrinterProvider();
94        if (provider != null) {
95            provider.setTrackedPrinter(printerId);
96        }
97    }
98
99    public boolean areHistoricalPrintersLoaded() {
100        FusedPrintersProvider provider = getPrinterProvider();
101        if (provider != null) {
102            return getPrinterProvider().areHistoricalPrintersLoaded();
103        }
104        return false;
105    }
106
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
166        public MyHandler(Looper looper) {
167            super(looper, null , false);
168        }
169
170        @Override
171        @SuppressWarnings("unchecked")
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