319 lines
10 KiB
Java
319 lines
10 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2013 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.print;
|
||
|
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.content.Context;
|
||
|
import android.content.pm.ParceledListSlice;
|
||
|
import android.os.Handler;
|
||
|
import android.os.Looper;
|
||
|
import android.os.Message;
|
||
|
import android.os.RemoteException;
|
||
|
import android.util.ArrayMap;
|
||
|
import android.util.Log;
|
||
|
|
||
|
import java.lang.ref.WeakReference;
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.Collections;
|
||
|
import java.util.LinkedHashMap;
|
||
|
import java.util.List;
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public final class PrinterDiscoverySession {
|
||
|
|
||
|
private static final String LOG_TAG ="PrinterDiscoverySession";
|
||
|
|
||
|
private static final int MSG_PRINTERS_ADDED = 1;
|
||
|
private static final int MSG_PRINTERS_REMOVED = 2;
|
||
|
|
||
|
private final LinkedHashMap<PrinterId, PrinterInfo> mPrinters =
|
||
|
new LinkedHashMap<PrinterId, PrinterInfo>();
|
||
|
|
||
|
private final IPrintManager mPrintManager;
|
||
|
|
||
|
private final int mUserId;
|
||
|
|
||
|
private final Handler mHandler;
|
||
|
|
||
|
private IPrinterDiscoveryObserver mObserver;
|
||
|
|
||
|
private OnPrintersChangeListener mListener;
|
||
|
|
||
|
private boolean mIsPrinterDiscoveryStarted;
|
||
|
|
||
|
public static interface OnPrintersChangeListener {
|
||
|
public void onPrintersChanged();
|
||
|
}
|
||
|
|
||
|
PrinterDiscoverySession(IPrintManager printManager, Context context, int userId) {
|
||
|
mPrintManager = printManager;
|
||
|
mUserId = userId;
|
||
|
mHandler = new SessionHandler(context.getMainLooper());
|
||
|
mObserver = new PrinterDiscoveryObserver(this);
|
||
|
try {
|
||
|
mPrintManager.createPrinterDiscoverySession(mObserver, mUserId);
|
||
|
} catch (RemoteException re) {
|
||
|
Log.e(LOG_TAG, "Error creating printer discovery session", re);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final void startPrinterDiscovery(@Nullable List<PrinterId> priorityList) {
|
||
|
if (isDestroyed()) {
|
||
|
Log.w(LOG_TAG, "Ignoring start printers discovery - session destroyed");
|
||
|
return;
|
||
|
}
|
||
|
if (!mIsPrinterDiscoveryStarted) {
|
||
|
mIsPrinterDiscoveryStarted = true;
|
||
|
try {
|
||
|
mPrintManager.startPrinterDiscovery(mObserver, priorityList, mUserId);
|
||
|
} catch (RemoteException re) {
|
||
|
Log.e(LOG_TAG, "Error starting printer discovery", re);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final void stopPrinterDiscovery() {
|
||
|
if (isDestroyed()) {
|
||
|
Log.w(LOG_TAG, "Ignoring stop printers discovery - session destroyed");
|
||
|
return;
|
||
|
}
|
||
|
if (mIsPrinterDiscoveryStarted) {
|
||
|
mIsPrinterDiscoveryStarted = false;
|
||
|
try {
|
||
|
mPrintManager.stopPrinterDiscovery(mObserver, mUserId);
|
||
|
} catch (RemoteException re) {
|
||
|
Log.e(LOG_TAG, "Error stopping printer discovery", re);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final void startPrinterStateTracking(@NonNull PrinterId printerId) {
|
||
|
if (isDestroyed()) {
|
||
|
Log.w(LOG_TAG, "Ignoring start printer state tracking - session destroyed");
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
mPrintManager.startPrinterStateTracking(printerId, mUserId);
|
||
|
} catch (RemoteException re) {
|
||
|
Log.e(LOG_TAG, "Error starting printer state tracking", re);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final void stopPrinterStateTracking(@NonNull PrinterId printerId) {
|
||
|
if (isDestroyed()) {
|
||
|
Log.w(LOG_TAG, "Ignoring stop printer state tracking - session destroyed");
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
mPrintManager.stopPrinterStateTracking(printerId, mUserId);
|
||
|
} catch (RemoteException re) {
|
||
|
Log.e(LOG_TAG, "Error stopping printer state tracking", re);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final void validatePrinters(List<PrinterId> printerIds) {
|
||
|
if (isDestroyed()) {
|
||
|
Log.w(LOG_TAG, "Ignoring validate printers - session destroyed");
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
mPrintManager.validatePrinters(printerIds, mUserId);
|
||
|
} catch (RemoteException re) {
|
||
|
Log.e(LOG_TAG, "Error validating printers", re);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final void destroy() {
|
||
|
if (isDestroyed()) {
|
||
|
Log.w(LOG_TAG, "Ignoring destroy - session destroyed");
|
||
|
}
|
||
|
destroyNoCheck();
|
||
|
}
|
||
|
|
||
|
public final List<PrinterInfo> getPrinters() {
|
||
|
if (isDestroyed()) {
|
||
|
Log.w(LOG_TAG, "Ignoring get printers - session destroyed");
|
||
|
return Collections.emptyList();
|
||
|
}
|
||
|
return new ArrayList<PrinterInfo>(mPrinters.values());
|
||
|
}
|
||
|
|
||
|
public final boolean isDestroyed() {
|
||
|
throwIfNotCalledOnMainThread();
|
||
|
return isDestroyedNoCheck();
|
||
|
}
|
||
|
|
||
|
public final boolean isPrinterDiscoveryStarted() {
|
||
|
throwIfNotCalledOnMainThread();
|
||
|
return mIsPrinterDiscoveryStarted;
|
||
|
}
|
||
|
|
||
|
public final void setOnPrintersChangeListener(OnPrintersChangeListener listener) {
|
||
|
throwIfNotCalledOnMainThread();
|
||
|
mListener = listener;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected final void finalize() throws Throwable {
|
||
|
if (!isDestroyedNoCheck()) {
|
||
|
Log.e(LOG_TAG, "Destroying leaked printer discovery session");
|
||
|
destroyNoCheck();
|
||
|
}
|
||
|
super.finalize();
|
||
|
}
|
||
|
|
||
|
private boolean isDestroyedNoCheck() {
|
||
|
return (mObserver == null);
|
||
|
}
|
||
|
|
||
|
private void destroyNoCheck() {
|
||
|
stopPrinterDiscovery();
|
||
|
try {
|
||
|
mPrintManager.destroyPrinterDiscoverySession(mObserver, mUserId);
|
||
|
} catch (RemoteException re) {
|
||
|
Log.e(LOG_TAG, "Error destroying printer discovery session", re);
|
||
|
} finally {
|
||
|
mObserver = null;
|
||
|
mPrinters.clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void handlePrintersAdded(List<PrinterInfo> addedPrinters) {
|
||
|
if (isDestroyed()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// No old printers - do not bother keeping their position.
|
||
|
if (mPrinters.isEmpty()) {
|
||
|
final int printerCount = addedPrinters.size();
|
||
|
for (int i = 0; i < printerCount; i++) {
|
||
|
PrinterInfo printer = addedPrinters.get(i);
|
||
|
mPrinters.put(printer.getId(), printer);
|
||
|
}
|
||
|
notifyOnPrintersChanged();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Add the printers to a map.
|
||
|
ArrayMap<PrinterId, PrinterInfo> addedPrintersMap =
|
||
|
new ArrayMap<PrinterId, PrinterInfo>();
|
||
|
final int printerCount = addedPrinters.size();
|
||
|
for (int i = 0; i < printerCount; i++) {
|
||
|
PrinterInfo printer = addedPrinters.get(i);
|
||
|
addedPrintersMap.put(printer.getId(), printer);
|
||
|
}
|
||
|
|
||
|
// Update printers we already have.
|
||
|
for (PrinterId oldPrinterId : mPrinters.keySet()) {
|
||
|
PrinterInfo updatedPrinter = addedPrintersMap.remove(oldPrinterId);
|
||
|
if (updatedPrinter != null) {
|
||
|
mPrinters.put(oldPrinterId, updatedPrinter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add the new printers, i.e. what is left.
|
||
|
mPrinters.putAll(addedPrintersMap);
|
||
|
|
||
|
// Announce the change.
|
||
|
notifyOnPrintersChanged();
|
||
|
}
|
||
|
|
||
|
private void handlePrintersRemoved(List<PrinterId> printerIds) {
|
||
|
if (isDestroyed()) {
|
||
|
return;
|
||
|
}
|
||
|
boolean printersChanged = false;
|
||
|
final int removedPrinterIdCount = printerIds.size();
|
||
|
for (int i = 0; i < removedPrinterIdCount; i++) {
|
||
|
PrinterId removedPrinterId = printerIds.get(i);
|
||
|
if (mPrinters.remove(removedPrinterId) != null) {
|
||
|
printersChanged = true;
|
||
|
}
|
||
|
}
|
||
|
if (printersChanged) {
|
||
|
notifyOnPrintersChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void notifyOnPrintersChanged() {
|
||
|
if (mListener != null) {
|
||
|
mListener.onPrintersChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void throwIfNotCalledOnMainThread() {
|
||
|
if (!Looper.getMainLooper().isCurrentThread()) {
|
||
|
throw new IllegalAccessError("must be called from the main thread");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private final class SessionHandler extends Handler {
|
||
|
|
||
|
public SessionHandler(Looper looper) {
|
||
|
super(looper, null, false);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@SuppressWarnings("unchecked")
|
||
|
public void handleMessage(Message message) {
|
||
|
switch (message.what) {
|
||
|
case MSG_PRINTERS_ADDED: {
|
||
|
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
|
||
|
handlePrintersAdded(printers);
|
||
|
} break;
|
||
|
|
||
|
case MSG_PRINTERS_REMOVED: {
|
||
|
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
|
||
|
handlePrintersRemoved(printerIds);
|
||
|
} break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub {
|
||
|
|
||
|
private final WeakReference<PrinterDiscoverySession> mWeakSession;
|
||
|
|
||
|
public PrinterDiscoveryObserver(PrinterDiscoverySession session) {
|
||
|
mWeakSession = new WeakReference<PrinterDiscoverySession>(session);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@SuppressWarnings("rawtypes")
|
||
|
public void onPrintersAdded(ParceledListSlice printers) {
|
||
|
PrinterDiscoverySession session = mWeakSession.get();
|
||
|
if (session != null) {
|
||
|
session.mHandler.obtainMessage(MSG_PRINTERS_ADDED,
|
||
|
printers.getList()).sendToTarget();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@SuppressWarnings("rawtypes")
|
||
|
public void onPrintersRemoved(ParceledListSlice printerIds) {
|
||
|
PrinterDiscoverySession session = mWeakSession.get();
|
||
|
if (session != null) {
|
||
|
session.mHandler.obtainMessage(MSG_PRINTERS_REMOVED,
|
||
|
printerIds.getList()).sendToTarget();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|