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.annotation.Nullable; 20 import android.app.Activity; 21 import android.app.LoaderManager.LoaderCallbacks; 22 import android.content.Loader; 23 import android.os.Bundle; 24 import android.os.Handler; 25 import android.os.Looper; 26 import android.os.Message; 27 import android.print.PrinterId; 28 import android.print.PrinterInfo; 29 import com.android.internal.os.SomeArgs; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 34 public 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