1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.printspooler; 18 19 import android.os.AsyncTask; 20 import android.os.Bundle; 21 import android.os.ParcelFileDescriptor; 22 import android.os.RemoteException; 23 import android.print.ILayoutResultCallback; 24 import android.print.IPrintDocumentAdapter; 25 import android.print.IWriteResultCallback; 26 import android.print.PageRange; 27 import android.print.PrintAttributes; 28 import android.util.Log; 29 30 import libcore.io.IoUtils; 31 32 import java.io.File; 33 import java.io.FileInputStream; 34 import java.io.FileOutputStream; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.io.OutputStream; 38 39 /** 40 * This class represents a remote print document adapter instance. 41 */ 42 final class RemotePrintDocumentAdapter { 43 private static final String LOG_TAG = "RemotePrintDocumentAdapter"; 44 45 private static final boolean DEBUG = false; 46 47 private final IPrintDocumentAdapter mRemoteInterface; 48 49 private final File mFile; 50 51 public RemotePrintDocumentAdapter(IPrintDocumentAdapter printAdatper, File file) { 52 mRemoteInterface = printAdatper; 53 mFile = file; 54 } 55 56 public void start() { 57 if (DEBUG) { 58 Log.i(LOG_TAG, "start()"); 59 } 60 try { 61 mRemoteInterface.start(); 62 } catch (RemoteException re) { 63 Log.e(LOG_TAG, "Error calling start()", re); 64 } 65 } 66 67 public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 68 ILayoutResultCallback callback, Bundle metadata, int sequence) { 69 if (DEBUG) { 70 Log.i(LOG_TAG, "layout()"); 71 } 72 try { 73 mRemoteInterface.layout(oldAttributes, newAttributes, callback, metadata, sequence); 74 } catch (RemoteException re) { 75 Log.e(LOG_TAG, "Error calling layout()", re); 76 } 77 } 78 79 public void write(final PageRange[] pages, final IWriteResultCallback callback, 80 final int sequence) { 81 if (DEBUG) { 82 Log.i(LOG_TAG, "write()"); 83 } 84 new AsyncTask<Void, Void, Void>() { 85 @Override 86 protected Void doInBackground(Void... params) { 87 InputStream in = null; 88 OutputStream out = null; 89 ParcelFileDescriptor source = null; 90 ParcelFileDescriptor sink = null; 91 try { 92 ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); 93 source = pipe[0]; 94 sink = pipe[1]; 95 96 in = new FileInputStream(source.getFileDescriptor()); 97 out = new FileOutputStream(mFile); 98 99 // Async call to initiate the other process writing the data. 100 mRemoteInterface.write(pages, sink, callback, sequence); 101 102 // Close the source. It is now held by the client. 103 sink.close(); 104 sink = null; 105 106 // Read the data. 107 final byte[] buffer = new byte[8192]; 108 while (true) { 109 final int readByteCount = in.read(buffer); 110 if (readByteCount < 0) { 111 break; 112 } 113 out.write(buffer, 0, readByteCount); 114 } 115 } catch (RemoteException re) { 116 Log.e(LOG_TAG, "Error calling write()", re); 117 } catch (IOException ioe) { 118 Log.e(LOG_TAG, "Error calling write()", ioe); 119 } finally { 120 IoUtils.closeQuietly(in); 121 IoUtils.closeQuietly(out); 122 IoUtils.closeQuietly(sink); 123 IoUtils.closeQuietly(source); 124 } 125 return null; 126 } 127 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); 128 } 129 130 public void finish() { 131 if (DEBUG) { 132 Log.i(LOG_TAG, "finish()"); 133 } 134 try { 135 mRemoteInterface.finish(); 136 } catch (RemoteException re) { 137 Log.e(LOG_TAG, "Error calling finish()", re); 138 } 139 } 140 141 public void cancel() { 142 if (DEBUG) { 143 Log.i(LOG_TAG, "cancel()"); 144 } 145 try { 146 mRemoteInterface.cancel(); 147 } catch (RemoteException re) { 148 Log.e(LOG_TAG, "Error calling cancel()", re); 149 } 150 } 151 } 152