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