Merge "Partial implementation for the favorite and available printer tracking." into klp-dev
This commit is contained in:
@@ -50,6 +50,12 @@
|
|||||||
android:theme="@style/PrintJobConfigActivityTheme">
|
android:theme="@style/PrintJobConfigActivityTheme">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ChoosePrinterActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@android:style/Theme.Holo.Light">
|
||||||
|
</activity>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".NotificationController$NotificationBroadcastReceiver"
|
android:name=".NotificationController$NotificationBroadcastReceiver"
|
||||||
android:exported="false" >
|
android:exported="false" >
|
||||||
|
|||||||
23
packages/PrintSpooler/res/layout/choose_printer_activity.xml
Normal file
23
packages/PrintSpooler/res/layout/choose_printer_activity.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/list_view"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
</ListView>
|
||||||
|
|
||||||
29
packages/PrintSpooler/res/menu/choose_printer_activity.xml
Normal file
29
packages/PrintSpooler/res/menu/choose_printer_activity.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
android:title="@string/search"
|
||||||
|
android:icon="@*android:drawable/ic_menu_search_holo_light"
|
||||||
|
android:actionViewClass="android.widget.SearchView"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:alphabeticShortcut="f"
|
||||||
|
android:imeOptions="actionSearch">
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -58,6 +58,11 @@
|
|||||||
<!-- Title for the temporary dialog show while an app is generating a print job. [CHAR LIMIT=30] -->
|
<!-- Title for the temporary dialog show while an app is generating a print job. [CHAR LIMIT=30] -->
|
||||||
<string name="generating_print_job">Generating print job</string>
|
<string name="generating_print_job">Generating print job</string>
|
||||||
|
|
||||||
|
<!-- Choose printer activity -->
|
||||||
|
|
||||||
|
<!-- Title for the share action bar menu item. [CHAR LIMIT=20] -->
|
||||||
|
<string name="search">Search</string>
|
||||||
|
|
||||||
<!-- Notifications -->
|
<!-- Notifications -->
|
||||||
|
|
||||||
<!-- Template for the notificaiton label for a printing print job. [CHAR LIMIT=25] -->
|
<!-- Template for the notificaiton label for a printing print job. [CHAR LIMIT=25] -->
|
||||||
|
|||||||
@@ -0,0 +1,285 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.printspooler;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.print.IPrinterDiscoverySessionController;
|
||||||
|
import android.print.IPrinterDiscoverySessionObserver;
|
||||||
|
import android.print.PrinterId;
|
||||||
|
import android.print.PrinterInfo;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is responsible to provide the available printers.
|
||||||
|
* It starts and stops printer discovery and manages the returned
|
||||||
|
* printers.
|
||||||
|
*/
|
||||||
|
public class AvailablePrinterProvider extends DataProvider<PrinterInfo>
|
||||||
|
implements DataLoader {
|
||||||
|
private static final String LOG_TAG = "AvailablePrinterProvider";
|
||||||
|
|
||||||
|
private final Set<PrinterId> mPrinteIdsSet = new ArraySet<PrinterId>();
|
||||||
|
|
||||||
|
private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
|
||||||
|
|
||||||
|
private final List<PrinterId> mPriorityList;
|
||||||
|
|
||||||
|
private PrinterDiscoverySession mDiscoverySession;
|
||||||
|
|
||||||
|
public AvailablePrinterProvider(Context context, List<PrinterId> priorityList) {
|
||||||
|
mDiscoverySession = new PrinterDiscoverySession(context.getMainLooper());
|
||||||
|
mPriorityList = priorityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startLoadData() {
|
||||||
|
mDiscoverySession.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopLoadData() {
|
||||||
|
mDiscoverySession.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mPrinters.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemIndex(PrinterInfo printer) {
|
||||||
|
return mPrinters.indexOf(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrinterInfo getItemAt(int index) {
|
||||||
|
return mPrinters.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshItem(int index) {
|
||||||
|
PrinterInfo printer = getItemAt(index);
|
||||||
|
mDiscoverySession.requestPrinterUpdate(printer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPrinters(List<PrinterInfo> printers) {
|
||||||
|
boolean addedPrinters = false;
|
||||||
|
|
||||||
|
final int addedPrinterCount = printers.size();
|
||||||
|
for (int i = 0; i < addedPrinterCount; i++) {
|
||||||
|
PrinterInfo addedPrinter = printers.get(i);
|
||||||
|
if (mPrinteIdsSet.add(addedPrinter.getId())) {
|
||||||
|
mPrinters.add(addedPrinter);
|
||||||
|
addedPrinters = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addedPrinters) {
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePrinters(List<PrinterInfo> printers) {
|
||||||
|
boolean updatedPrinters = false;
|
||||||
|
|
||||||
|
final int updatedPrinterCount = printers.size();
|
||||||
|
for (int i = 0; i < updatedPrinterCount; i++) {
|
||||||
|
PrinterInfo updatedPrinter = printers.get(i);
|
||||||
|
if (mPrinteIdsSet.contains(updatedPrinter.getId())) {
|
||||||
|
final int oldPrinterCount = mPrinters.size();
|
||||||
|
for (int j = 0; j < oldPrinterCount; j++) {
|
||||||
|
PrinterInfo oldPrinter = mPrinters.get(j);
|
||||||
|
if (updatedPrinter.getId().equals(oldPrinter.getId())) {
|
||||||
|
mPrinters.set(j, updatedPrinter);
|
||||||
|
updatedPrinters = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedPrinters) {
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removePrinters(List<PrinterId> printers) {
|
||||||
|
boolean removedPrinters = false;
|
||||||
|
|
||||||
|
final int removedPrinterCount = printers.size();
|
||||||
|
for (int i = 0; i < removedPrinterCount; i++) {
|
||||||
|
PrinterId removedPrinter = printers.get(i);
|
||||||
|
if (mPrinteIdsSet.contains(removedPrinter)) {
|
||||||
|
mPrinteIdsSet.remove(removedPrinter);
|
||||||
|
Iterator<PrinterInfo> iterator = mPrinters.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
PrinterInfo oldPrinter = iterator.next();
|
||||||
|
if (removedPrinter.equals(oldPrinter.getId())) {
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removedPrinters) {
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class PrinterDiscoverySession {
|
||||||
|
|
||||||
|
private final Handler mHandler;
|
||||||
|
|
||||||
|
private final IPrinterDiscoverySessionObserver mObserver;
|
||||||
|
|
||||||
|
private IPrinterDiscoverySessionController mController;
|
||||||
|
|
||||||
|
public PrinterDiscoverySession(Looper looper) {
|
||||||
|
mHandler = new SessionHandler(looper);
|
||||||
|
mObserver = new PrinterDiscoverySessionObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open() {
|
||||||
|
PrintSpooler.peekInstance().createPrinterDiscoverySession(
|
||||||
|
mObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if (mController != null) {
|
||||||
|
try {
|
||||||
|
mController.close();
|
||||||
|
} catch (RemoteException re) {
|
||||||
|
Log.e(LOG_TAG, "Error closing printer discovery session", re);
|
||||||
|
} finally {
|
||||||
|
mController = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestPrinterUpdate(PrinterId printerId) {
|
||||||
|
if (mController != null) {
|
||||||
|
try {
|
||||||
|
mController.requestPrinterUpdate(printerId);
|
||||||
|
} catch (RemoteException re) {
|
||||||
|
Log.e(LOG_TAG, "Error requesting printer udpdate", re);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class SessionHandler extends Handler {
|
||||||
|
public static final int MSG_SET_CONTROLLER = 1;
|
||||||
|
public static final int MSG_ON_PRINTERS_ADDED = 2;
|
||||||
|
public static final int MSG_ON_PRINTERS_REMOVED = 3;
|
||||||
|
public static final int MSG_ON_PRINTERS_UPDATED = 4;
|
||||||
|
|
||||||
|
public SessionHandler(Looper looper) {
|
||||||
|
super(looper, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void handleMessage(Message message) {
|
||||||
|
switch (message.what) {
|
||||||
|
case MSG_SET_CONTROLLER: {
|
||||||
|
mController = (IPrinterDiscoverySessionController) message.obj;
|
||||||
|
try {
|
||||||
|
mController.open(mPriorityList);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(LOG_TAG, "Error starting printer discovery");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MSG_ON_PRINTERS_ADDED: {
|
||||||
|
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
|
||||||
|
addPrinters(printers);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MSG_ON_PRINTERS_REMOVED: {
|
||||||
|
List<PrinterId> printers = (List<PrinterId>) message.obj;
|
||||||
|
removePrinters(printers);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MSG_ON_PRINTERS_UPDATED: {
|
||||||
|
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
|
||||||
|
updatePrinters(printers);
|
||||||
|
} break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PrinterDiscoverySessionObserver
|
||||||
|
extends IPrinterDiscoverySessionObserver.Stub {
|
||||||
|
|
||||||
|
private final WeakReference<PrinterDiscoverySession> mWeakSession;
|
||||||
|
|
||||||
|
public PrinterDiscoverySessionObserver(PrinterDiscoverySession session) {
|
||||||
|
mWeakSession = new WeakReference<PrinterDiscoverySession>(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setController(IPrinterDiscoverySessionController controller) {
|
||||||
|
PrinterDiscoverySession sesison = mWeakSession.get();
|
||||||
|
if (sesison != null) {
|
||||||
|
sesison.mHandler.obtainMessage(
|
||||||
|
PrinterDiscoverySession.SessionHandler.MSG_SET_CONTROLLER,
|
||||||
|
controller).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrintersAdded(List<PrinterInfo> printers) {
|
||||||
|
PrinterDiscoverySession sesison = mWeakSession.get();
|
||||||
|
if (sesison != null) {
|
||||||
|
sesison.mHandler.obtainMessage(
|
||||||
|
PrinterDiscoverySession.SessionHandler.MSG_ON_PRINTERS_ADDED,
|
||||||
|
printers).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrintersRemoved(List<PrinterId> printers) {
|
||||||
|
PrinterDiscoverySession session = mWeakSession.get();
|
||||||
|
if (session != null) {
|
||||||
|
session.mHandler.obtainMessage(
|
||||||
|
PrinterDiscoverySession.SessionHandler.MSG_ON_PRINTERS_REMOVED,
|
||||||
|
printers).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrintersUpdated(List<PrinterInfo> printers) {
|
||||||
|
PrinterDiscoverySession session = mWeakSession.get();
|
||||||
|
if (session != null) {
|
||||||
|
session.mHandler.obtainMessage(
|
||||||
|
PrinterDiscoverySession.SessionHandler.MSG_ON_PRINTERS_UPDATED,
|
||||||
|
printers).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.printspooler;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class ChoosePrinterActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle bundle) {
|
||||||
|
setContentView(R.layout.choose_printer_activity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.printspooler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the contract for a class that know how to load data.
|
||||||
|
*/
|
||||||
|
public interface DataLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests to start loading data.
|
||||||
|
*/
|
||||||
|
public void startLoadData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests to stop loading data.
|
||||||
|
*/
|
||||||
|
public void stopLoadData();
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.printspooler;
|
||||||
|
|
||||||
|
import android.database.DataSetObservable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the simple contract for data providers.
|
||||||
|
*
|
||||||
|
* @param <T> The type of the providers data.
|
||||||
|
*/
|
||||||
|
public abstract class DataProvider<T> extends DataSetObservable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of items.
|
||||||
|
*
|
||||||
|
* @return The item count.
|
||||||
|
*/
|
||||||
|
public abstract int getItemCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of an item.
|
||||||
|
*
|
||||||
|
* @param item The item.
|
||||||
|
* @return The item index.
|
||||||
|
*/
|
||||||
|
public abstract int getItemIndex(T item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an item at a given position.
|
||||||
|
*
|
||||||
|
* @param index The position.
|
||||||
|
* @return The item.
|
||||||
|
*/
|
||||||
|
public abstract T getItemAt(int index);
|
||||||
|
}
|
||||||
@@ -0,0 +1,364 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.printspooler;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.print.PrinterId;
|
||||||
|
import android.print.PrinterInfo;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
import android.util.AtomicFile;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Slog;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import com.android.internal.util.FastXmlSerializer;
|
||||||
|
|
||||||
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides the favorite printers based on past usage.
|
||||||
|
*/
|
||||||
|
final class FavoritePrinterProvider extends DataProvider<PrinterInfo> implements DataLoader {
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "FavoritePrinterProvider";
|
||||||
|
|
||||||
|
private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
|
||||||
|
|
||||||
|
private static final int MAX_HISTORY_LENGTH = 50;
|
||||||
|
|
||||||
|
private static final double WEIGHT_DECAY_COEFFICIENT = 0.95f;
|
||||||
|
|
||||||
|
private final List<PrinterRecord> mHistoricalPrinters = new ArrayList<PrinterRecord>();
|
||||||
|
|
||||||
|
private final List<PrinterRecord> mFavoritePrinters = new ArrayList<PrinterRecord>();
|
||||||
|
|
||||||
|
private final PersistenceManager mPersistenceManager;
|
||||||
|
|
||||||
|
public FavoritePrinterProvider(Context context) {
|
||||||
|
mPersistenceManager = new PersistenceManager(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPrinter(PrinterInfo printer) {
|
||||||
|
addPrinterInternal(printer);
|
||||||
|
computeFavoritePrinters();
|
||||||
|
mPersistenceManager.writeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mFavoritePrinters.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrinterInfo getItemAt(int index) {
|
||||||
|
return mFavoritePrinters.get(index).printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemIndex(PrinterInfo printer) {
|
||||||
|
return mFavoritePrinters.indexOf(printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startLoadData() {
|
||||||
|
mPersistenceManager.readStateLocked();
|
||||||
|
computeFavoritePrinters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopLoadData() {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPrinterInternal(PrinterInfo printer) {
|
||||||
|
if (mHistoricalPrinters.size() >= MAX_HISTORY_LENGTH) {
|
||||||
|
mHistoricalPrinters.remove(0);
|
||||||
|
}
|
||||||
|
mHistoricalPrinters.add(new PrinterRecord(printer));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeFavoritePrinters() {
|
||||||
|
Map<PrinterId, PrinterRecord> recordMap =
|
||||||
|
new ArrayMap<PrinterId, PrinterRecord>();
|
||||||
|
|
||||||
|
// Recompute the weights.
|
||||||
|
float currentWeight = 1.0f;
|
||||||
|
final int printerCount = mHistoricalPrinters.size();
|
||||||
|
for (int i = printerCount - 1; i >= 0; i--) {
|
||||||
|
PrinterRecord record = mHistoricalPrinters.get(i);
|
||||||
|
record.weight = currentWeight;
|
||||||
|
// Aggregate weight for the same printer
|
||||||
|
PrinterRecord oldRecord = recordMap.put(record.printer.getId(), record);
|
||||||
|
if (oldRecord != null) {
|
||||||
|
record.weight += oldRecord.weight;
|
||||||
|
}
|
||||||
|
currentWeight *= WEIGHT_DECAY_COEFFICIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the unique printer records with computed weights.
|
||||||
|
mFavoritePrinters.addAll(recordMap.values());
|
||||||
|
|
||||||
|
// Soft the favorite printers.
|
||||||
|
Collections.sort(mFavoritePrinters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class PrinterRecord implements Comparable<PrinterRecord> {
|
||||||
|
public final PrinterInfo printer;
|
||||||
|
public float weight;
|
||||||
|
|
||||||
|
public PrinterRecord(PrinterInfo printer) {
|
||||||
|
this.printer = printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(PrinterRecord another) {
|
||||||
|
return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class PersistenceManager {
|
||||||
|
private static final String PERSIST_FILE_NAME = "printer_history.xml";
|
||||||
|
|
||||||
|
private static final String TAG_PRINTERS = "printers";
|
||||||
|
|
||||||
|
private static final String TAG_PRINTER = "printer";
|
||||||
|
private static final String TAG_PRINTER_ID = "printerId";
|
||||||
|
|
||||||
|
private static final String ATTR_LOCAL_ID = "localId";
|
||||||
|
private static final String ATTR_SERVICE_NAME = "serviceName";
|
||||||
|
|
||||||
|
private static final String ATTR_NAME = "name";
|
||||||
|
private static final String ATTR_DESCRIPTION = "description";
|
||||||
|
private static final String ATTR_STATUS = "status";
|
||||||
|
|
||||||
|
private final AtomicFile mStatePersistFile;
|
||||||
|
|
||||||
|
private PersistenceManager(Context context) {
|
||||||
|
mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
|
||||||
|
PERSIST_FILE_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void writeState() {
|
||||||
|
|
||||||
|
new AsyncTask<List<PrinterRecord>, Void, Void>() {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(List<PrinterRecord>... printers) {
|
||||||
|
doWriteState(printers[0]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,
|
||||||
|
new ArrayList<PrinterRecord>(mHistoricalPrinters));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doWriteState(List<PrinterRecord> printers) {
|
||||||
|
FileOutputStream out = null;
|
||||||
|
try {
|
||||||
|
out = mStatePersistFile.startWrite();
|
||||||
|
|
||||||
|
XmlSerializer serializer = new FastXmlSerializer();
|
||||||
|
serializer.setOutput(out, "utf-8");
|
||||||
|
serializer.startDocument(null, true);
|
||||||
|
serializer.startTag(null, TAG_PRINTERS);
|
||||||
|
|
||||||
|
final int printerCount = printers.size();
|
||||||
|
for (int i = printerCount - 1; i >= 0; i--) {
|
||||||
|
PrinterInfo printer = printers.get(i).printer;
|
||||||
|
|
||||||
|
serializer.startTag(null, TAG_PRINTER);
|
||||||
|
|
||||||
|
serializer.attribute(null, ATTR_NAME, printer.getName());
|
||||||
|
serializer.attribute(null, ATTR_STATUS, String.valueOf(printer.getStatus()));
|
||||||
|
String description = printer.getDescription();
|
||||||
|
if (description != null) {
|
||||||
|
serializer.attribute(null, ATTR_DESCRIPTION, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrinterId printerId = printer.getId();
|
||||||
|
serializer.startTag(null, TAG_PRINTER_ID);
|
||||||
|
serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
|
||||||
|
serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
|
||||||
|
.flattenToString());
|
||||||
|
serializer.endTag(null, TAG_PRINTER_ID);
|
||||||
|
|
||||||
|
serializer.endTag(null, TAG_PRINTER);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "[PERSISTED] " + printer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer.endTag(null, TAG_PRINTERS);
|
||||||
|
serializer.endDocument();
|
||||||
|
mStatePersistFile.finishWrite(out);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "[PERSIST END]");
|
||||||
|
}
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Slog.w(LOG_TAG, "Failed to write printer history, restoring backup.", ioe);
|
||||||
|
mStatePersistFile.failWrite(out);
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readStateLocked() {
|
||||||
|
FileInputStream in = null;
|
||||||
|
try {
|
||||||
|
in = mStatePersistFile.openRead();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.i(LOG_TAG, "No existing printer history.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
XmlPullParser parser = Xml.newPullParser();
|
||||||
|
parser.setInput(in, null);
|
||||||
|
parseState(parser);
|
||||||
|
} catch (IllegalStateException ise) {
|
||||||
|
Slog.w(LOG_TAG, "Failed parsing ", ise);
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
Slog.w(LOG_TAG, "Failed parsing ", npe);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
Slog.w(LOG_TAG, "Failed parsing ", nfe);
|
||||||
|
} catch (XmlPullParserException xppe) {
|
||||||
|
Slog.w(LOG_TAG, "Failed parsing ", xppe);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Slog.w(LOG_TAG, "Failed parsing ", ioe);
|
||||||
|
} catch (IndexOutOfBoundsException iobe) {
|
||||||
|
Slog.w(LOG_TAG, "Failed parsing ", iobe);
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(in);
|
||||||
|
}
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseState(XmlPullParser parser)
|
||||||
|
throws IOException, XmlPullParserException {
|
||||||
|
parser.next();
|
||||||
|
skipEmptyTextTags(parser);
|
||||||
|
expect(parser, XmlPullParser.START_TAG, TAG_PRINTERS);
|
||||||
|
parser.next();
|
||||||
|
|
||||||
|
while (parsePrinter(parser)) {
|
||||||
|
parser.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
skipEmptyTextTags(parser);
|
||||||
|
expect(parser, XmlPullParser.END_TAG, TAG_PRINTERS);
|
||||||
|
|
||||||
|
// We were reading the new records first and appended them first,
|
||||||
|
// hence the historical list is in a reversed order, so fix that.
|
||||||
|
Collections.reverse(mHistoricalPrinters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean parsePrinter(XmlPullParser parser)
|
||||||
|
throws IOException, XmlPullParserException {
|
||||||
|
skipEmptyTextTags(parser);
|
||||||
|
if (!accept(parser, XmlPullParser.START_TAG, TAG_PRINTER)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = parser.getAttributeValue(null, ATTR_NAME);
|
||||||
|
String description = parser.getAttributeValue(null, ATTR_DESCRIPTION);
|
||||||
|
final int status = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATUS));
|
||||||
|
|
||||||
|
parser.next();
|
||||||
|
|
||||||
|
skipEmptyTextTags(parser);
|
||||||
|
expect(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID);
|
||||||
|
String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
|
||||||
|
ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
|
||||||
|
null, ATTR_SERVICE_NAME));
|
||||||
|
PrinterId printerId = new PrinterId(service, localId);
|
||||||
|
parser.next();
|
||||||
|
skipEmptyTextTags(parser);
|
||||||
|
expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
|
||||||
|
parser.next();
|
||||||
|
|
||||||
|
PrinterInfo.Builder builder = new PrinterInfo.Builder(printerId, name, status);
|
||||||
|
builder.setDescription(description);
|
||||||
|
PrinterInfo printer = builder.create();
|
||||||
|
|
||||||
|
addPrinterInternal(printer);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(LOG_TAG, "[RESTORED] " + printer);
|
||||||
|
}
|
||||||
|
|
||||||
|
skipEmptyTextTags(parser);
|
||||||
|
expect(parser, XmlPullParser.END_TAG, TAG_PRINTER);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expect(XmlPullParser parser, int type, String tag)
|
||||||
|
throws IOException, XmlPullParserException {
|
||||||
|
if (!accept(parser, type, tag)) {
|
||||||
|
throw new XmlPullParserException("Exepected event: " + type
|
||||||
|
+ " and tag: " + tag + " but got event: " + parser.getEventType()
|
||||||
|
+ " and tag:" + parser.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void skipEmptyTextTags(XmlPullParser parser)
|
||||||
|
throws IOException, XmlPullParserException {
|
||||||
|
while (accept(parser, XmlPullParser.TEXT, null)
|
||||||
|
&& "\n".equals(parser.getText())) {
|
||||||
|
parser.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean accept(XmlPullParser parser, int type, String tag)
|
||||||
|
throws IOException, XmlPullParserException {
|
||||||
|
if (parser.getEventType() != type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tag != null) {
|
||||||
|
if (!tag.equals(parser.getName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (parser.getName() != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import android.content.Context;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.database.DataSetObserver;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -34,8 +35,6 @@ import android.os.Message;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.print.ILayoutResultCallback;
|
import android.print.ILayoutResultCallback;
|
||||||
import android.print.IPrintDocumentAdapter;
|
import android.print.IPrintDocumentAdapter;
|
||||||
import android.print.IPrinterDiscoverySessionController;
|
|
||||||
import android.print.IPrinterDiscoverySessionObserver;
|
|
||||||
import android.print.IWriteResultCallback;
|
import android.print.IWriteResultCallback;
|
||||||
import android.print.PageRange;
|
import android.print.PageRange;
|
||||||
import android.print.PrintAttributes;
|
import android.print.PrintAttributes;
|
||||||
@@ -64,6 +63,7 @@ import android.view.inputmethod.InputMethodManager;
|
|||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
import android.widget.AdapterView.OnItemSelectedListener;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
@@ -72,7 +72,6 @@ import android.widget.TextView;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@@ -132,11 +131,13 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private PrintSpooler mSpooler;
|
|
||||||
private Editor mEditor;
|
private Editor mEditor;
|
||||||
private Document mDocument;
|
private Document mDocument;
|
||||||
private PrintController mController;
|
private PrintController mController;
|
||||||
private PrinterDiscoverySessionObserver mPrinterDiscoverySessionObserver;
|
|
||||||
|
private AvailablePrinterProvider mAvailablePrinters;
|
||||||
|
|
||||||
|
private FavoritePrinterProvider mFavoritePrinters;
|
||||||
|
|
||||||
private int mPrintJobId;
|
private int mPrintJobId;
|
||||||
|
|
||||||
@@ -168,12 +169,15 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
mCurrPrintAttributes.copyFrom(attributes);
|
mCurrPrintAttributes.copyFrom(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpooler = PrintSpooler.peekInstance();
|
// TODO: Use history
|
||||||
|
mAvailablePrinters = new AvailablePrinterProvider(this, null);
|
||||||
|
mFavoritePrinters = new FavoritePrinterProvider(this);
|
||||||
|
|
||||||
mEditor = new Editor();
|
mEditor = new Editor();
|
||||||
mDocument = new Document();
|
mDocument = new Document();
|
||||||
mController = new PrintController(new RemotePrintDocumentAdapter(
|
mController = new PrintController(new RemotePrintDocumentAdapter(
|
||||||
IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
|
IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
|
||||||
mSpooler.generateFileForPrintJob(mPrintJobId)));
|
PrintSpooler.peekInstance().generateFileForPrintJob(mPrintJobId)));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
|
mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
|
||||||
@@ -184,9 +188,26 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
|
|
||||||
mController.initialize();
|
mController.initialize();
|
||||||
mEditor.initialize();
|
mEditor.initialize();
|
||||||
mPrinterDiscoverySessionObserver = new PrinterDiscoverySessionObserver(mEditor,
|
}
|
||||||
getMainLooper());
|
|
||||||
mSpooler.createPrinterDiscoverySession(mPrinterDiscoverySessionObserver);
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
// TODO: Polish this
|
||||||
|
if (!mEditor.isPrintConfirmed()) {
|
||||||
|
mAvailablePrinters.startLoadData();
|
||||||
|
mFavoritePrinters.startLoadData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
// TODO: Polish this
|
||||||
|
if (!mEditor.isPrintConfirmed()) {
|
||||||
|
mAvailablePrinters.stopLoadData();
|
||||||
|
mFavoritePrinters.stopLoadData();
|
||||||
|
}
|
||||||
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -194,17 +215,14 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
// We can safely do the work in here since at this point
|
// We can safely do the work in here since at this point
|
||||||
// the system is bound to our (spooler) process which
|
// the system is bound to our (spooler) process which
|
||||||
// guarantees that this process will not be killed.
|
// guarantees that this process will not be killed.
|
||||||
mPrinterDiscoverySessionObserver.close();
|
|
||||||
mPrinterDiscoverySessionObserver.destroy();
|
|
||||||
mPrinterDiscoverySessionObserver = null;
|
|
||||||
if (mController.hasStarted()) {
|
if (mController.hasStarted()) {
|
||||||
mController.finish();
|
mController.finish();
|
||||||
}
|
}
|
||||||
if (mEditor.isPrintConfirmed() && mController.isFinished()) {
|
if (mEditor.isPrintConfirmed() && mController.isFinished()) {
|
||||||
mSpooler.setPrintJobState(mPrintJobId,
|
PrintSpooler.peekInstance().setPrintJobState(mPrintJobId,
|
||||||
PrintJobInfo.STATE_QUEUED, null);
|
PrintJobInfo.STATE_QUEUED, null);
|
||||||
} else {
|
} else {
|
||||||
mSpooler.setPrintJobState(mPrintJobId,
|
PrintSpooler.peekInstance().setPrintJobState(mPrintJobId,
|
||||||
PrintJobInfo.STATE_CANCELED, null);
|
PrintJobInfo.STATE_CANCELED, null);
|
||||||
}
|
}
|
||||||
mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
|
mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
|
||||||
@@ -320,7 +338,8 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
// completed and nothing changed, so we handle writing as usual.
|
// completed and nothing changed, so we handle writing as usual.
|
||||||
handleOnLayoutFinished(mDocument.info, false, mRequestCounter.get());
|
handleOnLayoutFinished(mDocument.info, false, mRequestCounter.get());
|
||||||
} else {
|
} else {
|
||||||
mSpooler.setPrintJobAttributesNoPersistence(mPrintJobId, mCurrPrintAttributes);
|
PrintSpooler.peekInstance().setPrintJobAttributesNoPersistence(mPrintJobId,
|
||||||
|
mCurrPrintAttributes);
|
||||||
|
|
||||||
mMetadata.putBoolean(PrintDocumentAdapter.METADATA_KEY_PRINT_PREVIEW,
|
mMetadata.putBoolean(PrintDocumentAdapter.METADATA_KEY_PRINT_PREVIEW,
|
||||||
!mEditor.isPrintConfirmed());
|
!mEditor.isPrintConfirmed());
|
||||||
@@ -353,15 +372,14 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mControllerState = CONTROLLER_STATE_LAYOUT_COMPLETED;
|
mControllerState = CONTROLLER_STATE_LAYOUT_COMPLETED;
|
||||||
|
mEditor.updateUi();
|
||||||
|
|
||||||
// If the info changed, we update the document and the print job,
|
// If the info changed, we update the document and the print job.
|
||||||
// and update the UI since the the page range selection may have
|
|
||||||
// become invalid.
|
|
||||||
final boolean infoChanged = !info.equals(mDocument.info);
|
final boolean infoChanged = !info.equals(mDocument.info);
|
||||||
if (infoChanged) {
|
if (infoChanged) {
|
||||||
mDocument.info = info;
|
mDocument.info = info;
|
||||||
mSpooler.setPrintJobPrintDocumentInfoNoPersistence(mPrintJobId, info);
|
PrintSpooler.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
|
||||||
mEditor.updateUi();
|
mPrintJobId, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the document info or the layout changed, then
|
// If the document info or the layout changed, then
|
||||||
@@ -447,11 +465,13 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
if (Arrays.equals(mDocument.pages, mRequestedPages)) {
|
if (Arrays.equals(mDocument.pages, mRequestedPages)) {
|
||||||
// We got a document with exactly the pages we wanted. Hence,
|
// We got a document with exactly the pages we wanted. Hence,
|
||||||
// the printer has to print all pages in the data.
|
// the printer has to print all pages in the data.
|
||||||
mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, ALL_PAGES_ARRAY);
|
PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
|
||||||
|
ALL_PAGES_ARRAY);
|
||||||
} else if (Arrays.equals(mDocument.pages, ALL_PAGES_ARRAY)) {
|
} else if (Arrays.equals(mDocument.pages, ALL_PAGES_ARRAY)) {
|
||||||
// We requested specific pages but got all of them. Hence,
|
// We requested specific pages but got all of them. Hence,
|
||||||
// the printer has to print only the requested pages.
|
// the printer has to print only the requested pages.
|
||||||
mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, mRequestedPages);
|
PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
|
||||||
|
mRequestedPages);
|
||||||
} else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
|
} else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
|
||||||
// We requested specific pages and got more but not all pages.
|
// We requested specific pages and got more but not all pages.
|
||||||
// Hence, we have to offset appropriately the printed pages to
|
// Hence, we have to offset appropriately the printed pages to
|
||||||
@@ -460,14 +480,16 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
final int offset = mDocument.pages[0].getStart() - pages[0].getStart();
|
final int offset = mDocument.pages[0].getStart() - pages[0].getStart();
|
||||||
PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length);
|
PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length);
|
||||||
PageRangeUtils.offsetStart(offsetPages, offset);
|
PageRangeUtils.offsetStart(offsetPages, offset);
|
||||||
mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, offsetPages);
|
PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
|
||||||
|
offsetPages);
|
||||||
} else if (Arrays.equals(mRequestedPages, ALL_PAGES_ARRAY)
|
} else if (Arrays.equals(mRequestedPages, ALL_PAGES_ARRAY)
|
||||||
&& mDocument.pages.length == 1 && mDocument.pages[0].getStart() == 0
|
&& mDocument.pages.length == 1 && mDocument.pages[0].getStart() == 0
|
||||||
&& mDocument.pages[0].getEnd() == mDocument.info.getPageCount() - 1) {
|
&& mDocument.pages[0].getEnd() == mDocument.info.getPageCount() - 1) {
|
||||||
// We requested all pages via the special constant and got all
|
// We requested all pages via the special constant and got all
|
||||||
// of them as an explicit enumeration. Hence, the printer has
|
// of them as an explicit enumeration. Hence, the printer has
|
||||||
// to print only the requested pages.
|
// to print only the requested pages.
|
||||||
mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, mDocument.pages);
|
PrintSpooler.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
|
||||||
|
mDocument.pages);
|
||||||
} else {
|
} else {
|
||||||
// We did not get the pages we requested, then the application
|
// We did not get the pages we requested, then the application
|
||||||
// misbehaves, so we fail quickly.
|
// misbehaves, so we fail quickly.
|
||||||
@@ -592,7 +614,7 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
private final EditText mRangeEditText;
|
private final EditText mRangeEditText;
|
||||||
|
|
||||||
private final Spinner mDestinationSpinner;
|
private final Spinner mDestinationSpinner;
|
||||||
private final ArrayAdapter<SpinnerItem<PrinterInfo>> mDestinationSpinnerAdapter;
|
private final DestinationAdapter mDestinationSpinnerAdapter;
|
||||||
|
|
||||||
private final Spinner mMediaSizeSpinner;
|
private final Spinner mMediaSizeSpinner;
|
||||||
private final ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
|
private final ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
|
||||||
@@ -623,15 +645,18 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mCurrPrintAttributes.clear();
|
mCurrPrintAttributes.clear();
|
||||||
SpinnerItem<PrinterInfo> dstItem = mDestinationSpinnerAdapter.getItem(position);
|
PrinterInfo printer = (PrinterInfo) mDestinationSpinnerAdapter
|
||||||
if (dstItem != null) {
|
.getItem(position);
|
||||||
PrinterInfo printer = dstItem.value;
|
if (printer != null) {
|
||||||
mSpooler.setPrintJobPrinterNoPersistence(mPrintJobId, printer);
|
PrintSpooler.peekInstance().setPrintJobPrinterNoPersistence(
|
||||||
|
mPrintJobId, printer);
|
||||||
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
|
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
|
||||||
if (capabilities == null) {
|
if (capabilities == null) {
|
||||||
List<PrinterId> printerIds = new ArrayList<PrinterId>();
|
List<PrinterId> printerIds = new ArrayList<PrinterId>();
|
||||||
printerIds.add(printer.getId());
|
printerIds.add(printer.getId());
|
||||||
mPrinterDiscoverySessionObserver.requestPrinterUpdate(printer.getId());
|
final int index = mAvailablePrinters.getItemIndex(printer);
|
||||||
|
mAvailablePrinters.refreshItem(index);
|
||||||
|
mWaitingForPrinterCapabilities = true;
|
||||||
//TODO: We need a timeout for the update.
|
//TODO: We need a timeout for the update.
|
||||||
} else {
|
} else {
|
||||||
capabilities.getDefaults(mCurrPrintAttributes);
|
capabilities.getDefaults(mCurrPrintAttributes);
|
||||||
@@ -728,7 +753,7 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mCopiesEditText.setError(null);
|
mCopiesEditText.setError(null);
|
||||||
mSpooler.setPrintJobCopiesNoPersistence(mPrintJobId, copies);
|
PrintSpooler.peekInstance().setPrintJobCopiesNoPersistence(mPrintJobId, copies);
|
||||||
updateUi();
|
updateUi();
|
||||||
|
|
||||||
if (hadErrors && !hasErrors() && printAttributesChanged()) {
|
if (hadErrors && !hasErrors() && printAttributesChanged()) {
|
||||||
@@ -805,6 +830,8 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
private boolean mIgnoreNextCopiesChange;
|
private boolean mIgnoreNextCopiesChange;
|
||||||
private boolean mIgnoreNextRangeChange;
|
private boolean mIgnoreNextRangeChange;
|
||||||
|
|
||||||
|
private boolean mWaitingForPrinterCapabilities;
|
||||||
|
|
||||||
public Editor() {
|
public Editor() {
|
||||||
// Content container
|
// Content container
|
||||||
mContentContainer = findViewById(R.id.content_container);
|
mContentContainer = findViewById(R.id.content_container);
|
||||||
@@ -812,13 +839,40 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
// Copies
|
// Copies
|
||||||
mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
|
mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
|
||||||
mCopiesEditText.setText(String.valueOf(MIN_COPIES));
|
mCopiesEditText.setText(String.valueOf(MIN_COPIES));
|
||||||
mSpooler.setPrintJobCopiesNoPersistence(mPrintJobId, MIN_COPIES);
|
PrintSpooler.peekInstance().setPrintJobCopiesNoPersistence(mPrintJobId, MIN_COPIES);
|
||||||
mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
|
mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
|
||||||
mCopiesEditText.selectAll();
|
mCopiesEditText.selectAll();
|
||||||
|
|
||||||
// Destination.
|
// Destination.
|
||||||
|
mDestinationSpinnerAdapter = new DestinationAdapter(mAvailablePrinters);
|
||||||
|
mDestinationSpinnerAdapter.registerDataSetObserver(new DataSetObserver() {
|
||||||
|
@Override
|
||||||
|
public void onChanged() {
|
||||||
|
// Maybe we did not have capabilities when the current printer was
|
||||||
|
// selected, but now the selected printer has capabilities. Generate
|
||||||
|
// a fake selection so the code in the selection change handling takes
|
||||||
|
// care of updating everything. This way the logic is in one place.
|
||||||
|
if (mWaitingForPrinterCapabilities) {
|
||||||
|
mWaitingForPrinterCapabilities = false;
|
||||||
|
PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
|
||||||
|
if (printer != null) {
|
||||||
|
if (printer.getCapabilities() != null) {
|
||||||
|
final int selectedPosition =
|
||||||
|
mDestinationSpinner.getSelectedItemPosition();
|
||||||
|
mOnItemSelectedListener.onItemSelected(mDestinationSpinner, null,
|
||||||
|
selectedPosition, selectedPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidated() {
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
});
|
||||||
mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
|
mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
|
||||||
mDestinationSpinnerAdapter = new DestinationAdapter();
|
|
||||||
mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
|
mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
|
||||||
mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
|
mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
|
||||||
|
|
||||||
@@ -877,7 +931,6 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mEditor.confirmPrint();
|
mEditor.confirmPrint();
|
||||||
updateUi();
|
|
||||||
mController.update();
|
mController.update();
|
||||||
showGeneratingPrintJobUi();
|
showGeneratingPrintJobUi();
|
||||||
}
|
}
|
||||||
@@ -1001,6 +1054,11 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
|
|
||||||
public void confirmPrint() {
|
public void confirmPrint() {
|
||||||
mEditorState = EDITOR_STATE_CONFIRMED_PRINT;
|
mEditorState = EDITOR_STATE_CONFIRMED_PRINT;
|
||||||
|
PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
|
||||||
|
if (printer != null) {
|
||||||
|
mFavoritePrinters.addPrinter(printer);
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPreviewConfirmed() {
|
public boolean isPreviewConfirmed() {
|
||||||
@@ -1063,8 +1121,8 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
|
|
||||||
final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
|
final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
|
||||||
|
|
||||||
if (selectedIndex < 0 || mDestinationSpinnerAdapter.getItem(
|
if (selectedIndex < 0 || ((PrinterInfo) mDestinationSpinnerAdapter.getItem(
|
||||||
selectedIndex).value.getCapabilities() == null) {
|
selectedIndex)).getCapabilities() == null) {
|
||||||
|
|
||||||
// Destination
|
// Destination
|
||||||
mDestinationSpinner.setEnabled(false);
|
mDestinationSpinner.setEnabled(false);
|
||||||
@@ -1121,16 +1179,12 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
mPrintButton.setEnabled(false);
|
mPrintButton.setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
PrintAttributes defaultAttributes = mTempPrintAttributes;
|
PrintAttributes defaultAttributes = mTempPrintAttributes;
|
||||||
PrinterInfo printer = mDestinationSpinnerAdapter.getItem(selectedIndex).value;
|
PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
|
||||||
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
|
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
|
||||||
printer.getCapabilities().getDefaults(defaultAttributes);
|
printer.getCapabilities().getDefaults(defaultAttributes);
|
||||||
|
|
||||||
// Destination
|
// Destination
|
||||||
if (mDestinationSpinnerAdapter.getCount() > 1) {
|
mDestinationSpinner.setEnabled(true);
|
||||||
mDestinationSpinner.setEnabled(true);
|
|
||||||
} else {
|
|
||||||
mDestinationSpinner.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copies
|
// Copies
|
||||||
mCopiesEditText.setEnabled(true);
|
mCopiesEditText.setEnabled(true);
|
||||||
@@ -1159,9 +1213,6 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
if (mediaSizeCount <= 0) {
|
if (mediaSizeCount <= 0) {
|
||||||
mMediaSizeSpinner.setEnabled(false);
|
mMediaSizeSpinner.setEnabled(false);
|
||||||
mMediaSizeSpinner.setSelection(AdapterView.INVALID_POSITION);
|
mMediaSizeSpinner.setSelection(AdapterView.INVALID_POSITION);
|
||||||
} else if (mediaSizeCount == 1) {
|
|
||||||
mMediaSizeSpinner.setEnabled(false);
|
|
||||||
mMediaSizeSpinner.setSelection(0);
|
|
||||||
} else {
|
} else {
|
||||||
mMediaSizeSpinner.setEnabled(true);
|
mMediaSizeSpinner.setEnabled(true);
|
||||||
final int selectedMediaSizeIndex = Math.max(mediaSizes.indexOf(
|
final int selectedMediaSizeIndex = Math.max(mediaSizes.indexOf(
|
||||||
@@ -1210,9 +1261,6 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
if (colorModeCount <= 0) {
|
if (colorModeCount <= 0) {
|
||||||
mColorModeSpinner.setEnabled(false);
|
mColorModeSpinner.setEnabled(false);
|
||||||
mColorModeSpinner.setSelection(AdapterView.INVALID_POSITION);
|
mColorModeSpinner.setSelection(AdapterView.INVALID_POSITION);
|
||||||
} else if (colorModeCount == 1) {
|
|
||||||
mColorModeSpinner.setEnabled(false);
|
|
||||||
mColorModeSpinner.setSelection(0);
|
|
||||||
} else {
|
} else {
|
||||||
mColorModeSpinner.setEnabled(true);
|
mColorModeSpinner.setEnabled(true);
|
||||||
final int selectedColorModeIndex = Integer.numberOfTrailingZeros(
|
final int selectedColorModeIndex = Integer.numberOfTrailingZeros(
|
||||||
@@ -1262,9 +1310,6 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
if (orientationCount <= 0) {
|
if (orientationCount <= 0) {
|
||||||
mOrientationSpinner.setEnabled(false);
|
mOrientationSpinner.setEnabled(false);
|
||||||
mOrientationSpinner.setSelection(AdapterView.INVALID_POSITION);
|
mOrientationSpinner.setSelection(AdapterView.INVALID_POSITION);
|
||||||
} else if (orientationCount == 1) {
|
|
||||||
mOrientationSpinner.setEnabled(false);
|
|
||||||
mOrientationSpinner.setSelection(0);
|
|
||||||
} else {
|
} else {
|
||||||
mOrientationSpinner.setEnabled(true);
|
mOrientationSpinner.setEnabled(true);
|
||||||
final int selectedOrientationIndex = Integer.numberOfTrailingZeros(
|
final int selectedOrientationIndex = Integer.numberOfTrailingZeros(
|
||||||
@@ -1336,99 +1381,6 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPrinters(List<PrinterInfo> addedPrinters) {
|
|
||||||
final int addedPrinterCount = addedPrinters.size();
|
|
||||||
for (int i = 0; i < addedPrinterCount; i++) {
|
|
||||||
PrinterInfo addedPrinter = addedPrinters.get(i);
|
|
||||||
boolean duplicate = false;
|
|
||||||
final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
|
|
||||||
for (int j = 0; j < existingPrinterCount; j++) {
|
|
||||||
PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
|
|
||||||
if (addedPrinter.getId().equals(existingPrinter.getId())) {
|
|
||||||
duplicate = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!duplicate) {
|
|
||||||
mDestinationSpinnerAdapter.add(new SpinnerItem<PrinterInfo>(
|
|
||||||
addedPrinter, addedPrinter.getName()));
|
|
||||||
} else {
|
|
||||||
Log.w(LOG_TAG, "Skipping a duplicate printer: " + addedPrinter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDestinationSpinner.getSelectedItemPosition() == AdapterView.INVALID_POSITION
|
|
||||||
&& mDestinationSpinnerAdapter.getCount() > 0) {
|
|
||||||
mDestinationSpinner.setSelection(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mEditor.updateUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removePrinters(List<PrinterId> pritnerIds) {
|
|
||||||
final int printerIdCount = pritnerIds.size();
|
|
||||||
for (int i = 0; i < printerIdCount; i++) {
|
|
||||||
PrinterId removedPrinterId = pritnerIds.get(i);
|
|
||||||
boolean removed = false;
|
|
||||||
final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
|
|
||||||
for (int j = 0; j < existingPrinterCount; j++) {
|
|
||||||
PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
|
|
||||||
if (removedPrinterId.equals(existingPrinter.getId())) {
|
|
||||||
mDestinationSpinnerAdapter.remove(mDestinationSpinnerAdapter.getItem(j));
|
|
||||||
removed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!removed) {
|
|
||||||
Log.w(LOG_TAG, "Ignoring not added printer with id: " + removedPrinterId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDestinationSpinner.getSelectedItemPosition() != AdapterView.INVALID_POSITION
|
|
||||||
&& mDestinationSpinnerAdapter.getCount() == 0) {
|
|
||||||
mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void updatePrinters(List<PrinterInfo> pritners) {
|
|
||||||
SpinnerItem<PrinterInfo> selectedItem =
|
|
||||||
(SpinnerItem<PrinterInfo>) mDestinationSpinner.getSelectedItem();
|
|
||||||
PrinterId selectedPrinterId = (selectedItem != null)
|
|
||||||
? selectedItem.value.getId() : null;
|
|
||||||
|
|
||||||
boolean updated = false;
|
|
||||||
|
|
||||||
final int printerCount = pritners.size();
|
|
||||||
for (int i = 0; i < printerCount; i++) {
|
|
||||||
PrinterInfo updatedPrinter = pritners.get(i);
|
|
||||||
final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
|
|
||||||
for (int j = 0; j < existingPrinterCount; j++) {
|
|
||||||
PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
|
|
||||||
if (updatedPrinter.getId().equals(existingPrinter.getId())) {
|
|
||||||
existingPrinter.copyFrom(updatedPrinter);
|
|
||||||
updated = true;
|
|
||||||
if (selectedPrinterId != null
|
|
||||||
&& selectedPrinterId.equals(updatedPrinter.getId())) {
|
|
||||||
// The selected printer was updated. We simulate a fake
|
|
||||||
// selection to reuse the normal printer change handling.
|
|
||||||
mOnItemSelectedListener.onItemSelected(mDestinationSpinner,
|
|
||||||
mDestinationSpinner.getSelectedView(),
|
|
||||||
mDestinationSpinner.getSelectedItemPosition(),
|
|
||||||
mDestinationSpinner.getSelectedItemId());
|
|
||||||
// TODO: This will reset the UI to the defaults for the
|
|
||||||
// printer. We may need to revisit this.
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (updated) {
|
|
||||||
mDestinationSpinnerAdapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasErrors() {
|
private boolean hasErrors() {
|
||||||
return mRangeEditText.getError() != null
|
return mRangeEditText.getError() != null
|
||||||
|| mCopiesEditText.getError() != null;
|
|| mCopiesEditText.getError() != null;
|
||||||
@@ -1455,10 +1407,39 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class DestinationAdapter extends ArrayAdapter<SpinnerItem<PrinterInfo>> {
|
private final class DestinationAdapter extends BaseAdapter {
|
||||||
|
private final AvailablePrinterProvider mProvider;
|
||||||
|
|
||||||
public DestinationAdapter() {
|
private final DataSetObserver mObserver = new DataSetObserver() {
|
||||||
super( PrintJobConfigActivity.this, R.layout.spinner_dropdown_item);
|
@Override
|
||||||
|
public void onChanged() {
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidated() {
|
||||||
|
notifyDataSetInvalidated();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public DestinationAdapter(AvailablePrinterProvider provider) {
|
||||||
|
mProvider = provider;
|
||||||
|
mProvider.registerObserver(mObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return mProvider.getItemCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getItem(int position) {
|
||||||
|
return mProvider.getItemAt(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1474,7 +1455,7 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
R.layout.spinner_dropdown_item, parent, false);
|
R.layout.spinner_dropdown_item, parent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrinterInfo printerInfo = getItem(position).value;
|
PrinterInfo printerInfo = mProvider.getItemAt(position);
|
||||||
TextView title = (TextView) convertView.findViewById(R.id.title);
|
TextView title = (TextView) convertView.findViewById(R.id.title);
|
||||||
title.setText(printerInfo.getName());
|
title.setText(printerInfo.getName());
|
||||||
|
|
||||||
@@ -1495,132 +1476,6 @@ public class PrintJobConfigActivity extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class PrinterDiscoverySessionObserver
|
|
||||||
extends IPrinterDiscoverySessionObserver.Stub {
|
|
||||||
private static final int MSG_SET_CONTROLLER = 1;
|
|
||||||
private static final int MSG_ON_PRINTERS_ADDED = 2;
|
|
||||||
private static final int MSG_ON_PRINTERS_REMOVED = 3;
|
|
||||||
private static final int MSG_ON_PRINTERS_UPDATED = 4;
|
|
||||||
|
|
||||||
private Handler mHandler;
|
|
||||||
private Editor mEditor;
|
|
||||||
private IPrinterDiscoverySessionController mController;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public PrinterDiscoverySessionObserver(Editor editor, Looper looper) {
|
|
||||||
mEditor = editor;
|
|
||||||
mHandler = new Handler(looper, null, true) {
|
|
||||||
@Override
|
|
||||||
public void handleMessage(Message message) {
|
|
||||||
switch (message.what) {
|
|
||||||
case MSG_SET_CONTROLLER: {
|
|
||||||
mController = (IPrinterDiscoverySessionController) message.obj;
|
|
||||||
// TODO: This should be cleaned up
|
|
||||||
List<PrinterId> printerIds = Collections.emptyList();
|
|
||||||
try {
|
|
||||||
mController.open(printerIds);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(LOG_TAG, "Error starting printer discovery");
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MSG_ON_PRINTERS_ADDED: {
|
|
||||||
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
|
|
||||||
mEditor.addPrinters(printers);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MSG_ON_PRINTERS_REMOVED: {
|
|
||||||
List<PrinterId> printerIds = (List<PrinterId>) message.obj;
|
|
||||||
mEditor.removePrinters(printerIds);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case MSG_ON_PRINTERS_UPDATED: {
|
|
||||||
List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
|
|
||||||
mEditor.updatePrinters(printers);
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void open(List<PrinterId> priorityList) {
|
|
||||||
if (mController != null) {
|
|
||||||
try {
|
|
||||||
mController.open(priorityList);
|
|
||||||
} catch (RemoteException re) {
|
|
||||||
Log.e(LOG_TAG, "Error closing printer discovery session", re);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
if (mController != null) {
|
|
||||||
try {
|
|
||||||
mController.close();
|
|
||||||
} catch (RemoteException re) {
|
|
||||||
Log.e(LOG_TAG, "Error closing printer discovery session", re);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestPrinterUpdate(PrinterId printerId) {
|
|
||||||
if (mController != null) {
|
|
||||||
try {
|
|
||||||
mController.requestPrinterUpdate(printerId);
|
|
||||||
} catch (RemoteException re) {
|
|
||||||
Log.e(LOG_TAG, "Error requestin printer update", re);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setController(IPrinterDiscoverySessionController controller) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (mHandler != null) {
|
|
||||||
mHandler.obtainMessage(MSG_SET_CONTROLLER, controller)
|
|
||||||
.sendToTarget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPrintersAdded(List<PrinterInfo> printers) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (mHandler != null) {
|
|
||||||
mHandler.obtainMessage(MSG_ON_PRINTERS_ADDED, printers)
|
|
||||||
.sendToTarget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPrintersRemoved(List<PrinterId> printers) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (mHandler != null) {
|
|
||||||
mHandler.obtainMessage(MSG_ON_PRINTERS_REMOVED, printers)
|
|
||||||
.sendToTarget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPrintersUpdated(List<PrinterInfo> printers) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (mHandler != null) {
|
|
||||||
mHandler.obtainMessage(MSG_ON_PRINTERS_UPDATED, printers)
|
|
||||||
.sendToTarget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() {
|
|
||||||
synchronized (this) {
|
|
||||||
mHandler = null;
|
|
||||||
mEditor = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance of this class class is intended to be the first focusable
|
* An instance of this class class is intended to be the first focusable
|
||||||
* in a layout to which the system automatically gives focus. It performs
|
* in a layout to which the system automatically gives focus. It performs
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ public class PrintSpooler {
|
|||||||
private static final String ATTR_FITTING_MODE = "fittingMode";
|
private static final String ATTR_FITTING_MODE = "fittingMode";
|
||||||
private static final String ATTR_ORIENTATION = "orientation";
|
private static final String ATTR_ORIENTATION = "orientation";
|
||||||
|
|
||||||
private static final String ATTR_PRINTER_NAME = "printerName";
|
private static final String ATTR_LOCAL_ID = "printerName";
|
||||||
private static final String ATTR_SERVICE_NAME = "serviceName";
|
private static final String ATTR_SERVICE_NAME = "serviceName";
|
||||||
|
|
||||||
private static final String ATTR_WIDTH_MILS = "widthMils";
|
private static final String ATTR_WIDTH_MILS = "widthMils";
|
||||||
@@ -568,7 +568,7 @@ public class PrintSpooler {
|
|||||||
PrinterId printerId = printJob.getPrinterId();
|
PrinterId printerId = printJob.getPrinterId();
|
||||||
if (printerId != null) {
|
if (printerId != null) {
|
||||||
serializer.startTag(null, TAG_PRINTER_ID);
|
serializer.startTag(null, TAG_PRINTER_ID);
|
||||||
serializer.attribute(null, ATTR_PRINTER_NAME, printerId.getLocalId());
|
serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
|
||||||
serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
|
serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
|
||||||
.flattenToString());
|
.flattenToString());
|
||||||
serializer.endTag(null, TAG_PRINTER_ID);
|
serializer.endTag(null, TAG_PRINTER_ID);
|
||||||
@@ -695,13 +695,7 @@ public class PrintSpooler {
|
|||||||
Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
|
Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
|
||||||
mStatePersistFile.failWrite(out);
|
mStatePersistFile.failWrite(out);
|
||||||
} finally {
|
} finally {
|
||||||
if (out != null) {
|
IoUtils.closeQuietly(out);
|
||||||
try {
|
|
||||||
out.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,11 +727,7 @@ public class PrintSpooler {
|
|||||||
} catch (IndexOutOfBoundsException iobe) {
|
} catch (IndexOutOfBoundsException iobe) {
|
||||||
Slog.w(LOG_TAG, "Failed parsing ", iobe);
|
Slog.w(LOG_TAG, "Failed parsing ", iobe);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
IoUtils.closeQuietly(in);
|
||||||
in.close();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,7 +774,7 @@ public class PrintSpooler {
|
|||||||
|
|
||||||
skipEmptyTextTags(parser);
|
skipEmptyTextTags(parser);
|
||||||
if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
|
if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
|
||||||
String localId = parser.getAttributeValue(null, ATTR_PRINTER_NAME);
|
String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
|
||||||
ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
|
ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
|
||||||
null, ATTR_SERVICE_NAME));
|
null, ATTR_SERVICE_NAME));
|
||||||
printJob.setPrinterId(new PrinterId(service, localId));
|
printJob.setPrinterId(new PrinterId(service, localId));
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleBinderDied() {
|
private void handleBinderDied() {
|
||||||
|
mPendingCommands.clear();
|
||||||
ensureUnbound();
|
ensureUnbound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user