PrintManager.java revision 88d199130d44c6bacb383a7757e782cf97483c68
14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/* 24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project 34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License. 64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at 74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and 144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License. 154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage android.print; 184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Context; 204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender; 214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender.SendIntentException; 226283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslavimport android.os.Bundle; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal; 244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Handler; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ICancellationSignal; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Looper; 274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor; 294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException; 30a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.LayoutResultCallback; 31a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.WriteResultCallback; 3288d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganovimport android.text.TextUtils; 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.internal.os.SomeArgs; 364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport libcore.io.IoUtils; 384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.File; 404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileDescriptor; 414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.lang.ref.WeakReference; 424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList; 434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Collections; 444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List; 454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * System level service for accessing the printing capabilities of the platform. 484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * To obtain a handle to the print manager do the following: 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> 524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * PrintManager printManager = 534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * (PrintManager) context.getSystemService(Context.PRINT_SERVICE); 544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </pre> 554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintManager { 574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private static final String LOG_TAG = "PrintManager"; 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** @hide */ 614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final int APP_ID_ANY = -2; 624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Context mContext; 644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final IPrintManager mService; 664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final int mUserId; 684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final int mAppId; 704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final PrintClient mPrintClient; 724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Handler mHandler; 744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Creates a new instance. 774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param context The current context in which to operate. 794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param service The backing system service. 804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @hide 824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintManager(Context context, IPrintManager service, int userId, int appId) { 844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mContext = context; 854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mService = service; 864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mUserId = userId; 874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mAppId = appId; 884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mPrintClient = new PrintClient(this); 894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mHandler = new Handler(context.getMainLooper(), null, false) { 904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov SomeArgs args = (SomeArgs) message.obj; 934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Context context = (Context) args.arg1; 944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov IntentSender intent = (IntentSender) args.arg2; 954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov args.recycle(); 964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov context.startIntentSender(intent, null, 0, 0, 0); 984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (SendIntentException sie) { 994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Log.e(LOG_TAG, "Couldn't start print job config activity.", sie); 1004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }; 1034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Creates an instance that can access all print jobs. 1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param userId The user id for which to get all print jobs. 109a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * @return An instance if the caller has the permission to access 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * all print jobs, null otherwise. 1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @hide 1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintManager getGlobalPrintManagerForUser(int userId) { 1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new PrintManager(mContext, mService, userId, APP_ID_ANY); 1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 118a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintJobInfo getPrintJobInfo(int printJobId) { 1194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 120a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mService.getPrintJobInfo(printJobId, mAppId, mUserId); 1214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 122a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error getting a print job info:" + printJobId, re); 1234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return null; 1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Gets the print jobs for this application. 1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @return The print job list. 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @see PrintJob 1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public List<PrintJob> getPrintJobs() { 1354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 136a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId); 1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (printJobInfos == null) { 1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return Collections.emptyList(); 1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int printJobCount = printJobInfos.size(); 1414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov List<PrintJob> printJobs = new ArrayList<PrintJob>(printJobCount); 1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov for (int i = 0; i < printJobCount; i++) { 1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov printJobs.add(new PrintJob(printJobInfos.get(i), this)); 1444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return printJobs; 1464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 147a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error getting print jobs", re); 1484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return Collections.emptyList(); 1504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 152a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov void cancelPrintJob(int printJobId) { 1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mService.cancelPrintJob(printJobId, mAppId, mUserId); 1554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 156a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error cancleing a print job: " + printJobId, re); 1574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 1614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Creates a print job for printing a file with default print attributes. 1624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 1634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param printJobName A name for the new print job. 1644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param pdfFile The PDF file to print. 1654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param attributes The default print job attributes. 1664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @return The created print job. 167fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav * 168fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav * @see PrintJob 1694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintJob print(String printJobName, File pdfFile, PrintAttributes attributes) { 17117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav FileDocumentAdapter documentAdapter = new FileDocumentAdapter(mContext, pdfFile); 172a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return print(printJobName, documentAdapter, attributes); 1734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 176a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * Creates a print job for printing a {@link PrintDocumentAdapter} with default print 1774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * attributes. 1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 1794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param printJobName A name for the new print job. 180a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * @param documentAdapter An adapter that emits the document to print. 1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param attributes The default print job attributes. 1824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @return The created print job. 183fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav * 184fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav * @see PrintJob 1854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 186a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter, 1874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov PrintAttributes attributes) { 18888d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov if (TextUtils.isEmpty(printJobName)) { 18988d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov throw new IllegalArgumentException("priintJobName cannot be empty"); 19088d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov } 191a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(documentAdapter, 1924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mContext.getMainLooper()); 1934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 1944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov PrintJobInfo printJob = mService.print(printJobName, mPrintClient, delegate, 1954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov attributes, mAppId, mUserId); 1964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (printJob != null) { 1974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new PrintJob(printJob, this); 1984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 2004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Log.e(LOG_TAG, "Error creating a print job", re); 2014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return null; 2034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private static final class PrintClient extends IPrintClient.Stub { 2064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final WeakReference<PrintManager> mWeakPrintManager; 2084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintClient(PrintManager manager) { 2104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mWeakPrintManager = new WeakReference<PrintManager>(manager); 2114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 2144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void startPrintJobConfigActivity(IntentSender intent) { 2154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov PrintManager manager = mWeakPrintManager.get(); 2164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (manager != null) { 2174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov SomeArgs args = SomeArgs.obtain(); 2184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov args.arg1 = manager.mContext; 2194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov args.arg2 = intent; 2204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov manager.mHandler.obtainMessage(0, args).sendToTarget(); 2214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 225a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub { 226a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in finish() 2274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 228a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private Handler mHandler; // Strong reference OK - cleared in finish() 2294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 230a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) { 231a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter = documentAdapter; 2324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mHandler = new MyHandler(looper); 2334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 2364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void start() { 237a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mHandler.sendEmptyMessage(MyHandler.MSG_START); 2384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 2416283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 2426283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav ILayoutResultCallback callback, Bundle metadata) { 243a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov SomeArgs args = SomeArgs.obtain(); 244a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov args.arg1 = oldAttributes; 245a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov args.arg2 = newAttributes; 246a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov args.arg3 = callback; 2476283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav args.arg4 = metadata; 248a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mHandler.obtainMessage(MyHandler.MSG_LAYOUT, args).sendToTarget(); 2494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 252a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void write(List<PageRange> pages, ParcelFileDescriptor fd, 253a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov IWriteResultCallback callback) { 254a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov SomeArgs args = SomeArgs.obtain(); 255a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov args.arg1 = pages; 256a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov args.arg2 = fd.getFileDescriptor(); 257a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov args.arg3 = callback; 258a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mHandler.obtainMessage(MyHandler.MSG_WRITE, args).sendToTarget(); 2594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 2624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void finish() { 263a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mHandler.sendEmptyMessage(MyHandler.MSG_FINISH); 2644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 266a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private boolean isFinished() { 267a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mDocumentAdapter == null; 2684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 270a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void doFinish() { 271a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter = null; 2724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mHandler = null; 2734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final class MyHandler extends Handler { 276a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public static final int MSG_START = 1; 277a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public static final int MSG_LAYOUT = 2; 278a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public static final int MSG_WRITE = 3; 279a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public static final int MSG_FINISH = 4; 2804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public MyHandler(Looper looper) { 2824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super(looper, null, true); 2834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 286a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @SuppressWarnings("unchecked") 2874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 288a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (isFinished()) { 289a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return; 290a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 2914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov switch (message.what) { 292a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov case MSG_START: { 293a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter.onStart(); 2944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 2954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 296a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov case MSG_LAYOUT: { 2974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov SomeArgs args = (SomeArgs) message.obj; 298a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintAttributes oldAttributes = (PrintAttributes) args.arg1; 299a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintAttributes newAttributes = (PrintAttributes) args.arg2; 300a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov ILayoutResultCallback callback = (ILayoutResultCallback) args.arg3; 3016283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav Bundle metadata = (Bundle) args.arg4; 3024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov args.recycle(); 303a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 304a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 305a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov ICancellationSignal remoteSignal = CancellationSignal.createTransport(); 306a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov callback.onLayoutStarted(remoteSignal); 307a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 308a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter.onLayout(oldAttributes, newAttributes, 309a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov CancellationSignal.fromTransport(remoteSignal), 3106283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav new LayoutResultCallbackWrapper(callback), metadata); 311a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 312a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error printing", re); 313a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 3144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 3154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 316a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov case MSG_WRITE: { 3174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov SomeArgs args = (SomeArgs) message.obj; 318a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov List<PageRange> pages = (List<PageRange>) args.arg1; 319a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov FileDescriptor fd = (FileDescriptor) args.arg2; 320a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov IWriteResultCallback callback = (IWriteResultCallback) args.arg3; 3214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov args.recycle(); 322a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 3234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 3244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov ICancellationSignal remoteSignal = CancellationSignal.createTransport(); 325a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov callback.onWriteStarted(remoteSignal); 326a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 327a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter.onWrite(pages, fd, 328a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov CancellationSignal.fromTransport(remoteSignal), 329a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov new WriteResultCallbackWrapper(callback, fd)); 3304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 3314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Log.e(LOG_TAG, "Error printing", re); 3324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov IoUtils.closeQuietly(fd); 3334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 3354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 336a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov case MSG_FINISH: { 337a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter.onFinish(); 338a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov doFinish(); 3394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 3404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov default: { 3424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("Unknown message: " 3434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov + message.what); 3444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 350a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class WriteResultCallbackWrapper extends WriteResultCallback { 351a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 352a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final IWriteResultCallback mWrappedCallback; 353a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final FileDescriptor mFd; 354a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 355a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public WriteResultCallbackWrapper(IWriteResultCallback callback, 356a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov FileDescriptor fd) { 357a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mWrappedCallback = callback; 358a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mFd = fd; 359a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 360a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 361a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 362a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onWriteFinished(List<PageRange> pages) { 363a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 364a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // Close before notifying the other end. We want 365a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // to be ready by the time we announce it. 366a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov IoUtils.closeQuietly(mFd); 367a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mWrappedCallback.onWriteFinished(pages); 368a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 369a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error calling onWriteFinished", re); 370a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 371a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 372a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 373a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 374a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onWriteFailed(CharSequence error) { 375a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 376a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // Close before notifying the other end. We want 377a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // to be ready by the time we announce it. 378a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov IoUtils.closeQuietly(mFd); 379a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mWrappedCallback.onWriteFailed(error); 380a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 381a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error calling onWriteFailed", re); 382a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 383a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 384a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 385a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 386a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class LayoutResultCallbackWrapper extends LayoutResultCallback { 3874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 388a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final ILayoutResultCallback mWrappedCallback; 3894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 390a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public LayoutResultCallbackWrapper(ILayoutResultCallback callback) { 391fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav mWrappedCallback = callback; 3924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 395a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { 3964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 397a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mWrappedCallback.onLayoutFinished(info, changed); 3984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 399a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error calling onLayoutFinished", re); 4004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 4034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 404a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onLayoutFailed(CharSequence error) { 4054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 406a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mWrappedCallback.onLayoutFailed(error); 4074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 408a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error calling onLayoutFailed", re); 4094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 413