1e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn/* 2e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project 3e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * 4e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * you may not use this file except in compliance with the License. 6e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * You may obtain a copy of the License at 7e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * 8e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * 10e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * See the License for the specific language governing permissions and 14e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * limitations under the License. 15e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn */ 16e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 17cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackbornpackage com.android.internal.os; 18e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 19c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport android.annotation.NonNull; 20c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport android.annotation.Nullable; 21e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.Binder; 22e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.IBinder; 23e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.IInterface; 24e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.ParcelFileDescriptor; 25e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.RemoteException; 26e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.SystemClock; 27e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.util.Slog; 28e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 29c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport libcore.io.IoUtils; 30c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann 31c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport java.io.ByteArrayOutputStream; 32c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport java.io.Closeable; 33c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport java.io.FileDescriptor; 34c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport java.io.FileInputStream; 35c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport java.io.FileOutputStream; 36c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmannimport java.io.IOException; 37983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adamsimport java.io.OutputStream; 38c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann 39e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn/** 40e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * Helper for transferring data through a pipe from a client app. 41e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn */ 42983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adamspublic class TransferPipe implements Runnable, Closeable { 43e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn static final String TAG = "TransferPipe"; 44e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn static final boolean DEBUG = false; 45e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 46e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn static final long DEFAULT_TIMEOUT = 5000; // 5 seconds 47e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 48850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey final Thread mThread; 49e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn final ParcelFileDescriptor[] mFds; 50e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 51e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn FileDescriptor mOutFd; 52e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn long mEndTime; 53e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn String mFailure; 54e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn boolean mComplete; 55e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 56e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn String mBufferPrefix; 57e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 58e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn interface Caller { 59e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn void go(IInterface iface, FileDescriptor fd, String prefix, 60e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn String[] args) throws RemoteException; 61e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 62e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 63cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn public TransferPipe() throws IOException { 64850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey this(null); 65850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey } 66850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey 67850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey public TransferPipe(String bufferPrefix) throws IOException { 68983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams this(bufferPrefix, "TransferPipe"); 69983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams } 70983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams 71983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams protected TransferPipe(String bufferPrefix, String threadName) throws IOException { 72983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams mThread = new Thread(this, threadName); 73e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mFds = ParcelFileDescriptor.createPipe(); 74850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey mBufferPrefix = bufferPrefix; 75e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 76e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 77e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn ParcelFileDescriptor getReadFd() { 78e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn return mFds[0]; 79e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 80e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 81cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn public ParcelFileDescriptor getWriteFd() { 82e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn return mFds[1]; 83e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 84e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 85cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn public void setBufferPrefix(String prefix) { 86e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mBufferPrefix = prefix; 87e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 88e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 89850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey public static void dumpAsync(IBinder binder, FileDescriptor out, String[] args) 90850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey throws IOException, RemoteException { 91850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey goDump(binder, out, args); 92850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey } 93850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey 94c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann /** 95c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann * Read raw bytes from a service's dump function. 96c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann * 97c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann * <p>This can be used for dumping {@link android.util.proto.ProtoOutputStream protos}. 98c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann * 99c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann * @param binder The service providing the data 100c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann * @param args The arguments passed to the dump function of the service 101c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann */ 102c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann public static byte[] dumpAsync(@NonNull IBinder binder, @Nullable String... args) 103c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann throws IOException, RemoteException { 104c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); 105c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann try { 106c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann TransferPipe.dumpAsync(binder, pipe[1].getFileDescriptor(), args); 107c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann 108c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann // Data is written completely when dumpAsync is done 109c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann pipe[1].close(); 110c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann pipe[1] = null; 111c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann 112c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann byte[] buffer = new byte[4096]; 113c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann try (ByteArrayOutputStream combinedBuffer = new ByteArrayOutputStream()) { 114c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann try (FileInputStream is = new FileInputStream(pipe[0].getFileDescriptor())) { 115c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann while (true) { 116c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann int numRead = is.read(buffer); 117c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann if (numRead == -1) { 118c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann break; 119c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann } 120c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann 121c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann combinedBuffer.write(buffer, 0, numRead); 122c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann } 123c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann } 124c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann 125c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann return combinedBuffer.toByteArray(); 126c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann } 127c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann } finally { 128c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann pipe[0].close(); 129c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann IoUtils.closeQuietly(pipe[1]); 130c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann } 131c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann } 132c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8Philip P. Moltmann 133e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn static void go(Caller caller, IInterface iface, FileDescriptor out, 134e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn String prefix, String[] args) throws IOException, RemoteException { 135e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn go(caller, iface, out, prefix, args, DEFAULT_TIMEOUT); 136e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 137e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 138e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn static void go(Caller caller, IInterface iface, FileDescriptor out, 139e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn String prefix, String[] args, long timeout) throws IOException, RemoteException { 140e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if ((iface.asBinder()) instanceof Binder) { 141e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn // This is a local object... just call it directly. 142e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn try { 143e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn caller.go(iface, out, prefix, args); 144e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } catch (RemoteException e) { 145e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 146e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn return; 147e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 148e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 149850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey try (TransferPipe tp = new TransferPipe()) { 150e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn caller.go(iface, tp.getWriteFd().getFileDescriptor(), prefix, args); 151e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn tp.go(out, timeout); 152e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 153e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 154e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 155e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn static void goDump(IBinder binder, FileDescriptor out, 156e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn String[] args) throws IOException, RemoteException { 157e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn goDump(binder, out, args, DEFAULT_TIMEOUT); 158e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 159e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 160e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn static void goDump(IBinder binder, FileDescriptor out, 161e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn String[] args, long timeout) throws IOException, RemoteException { 162e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (binder instanceof Binder) { 163e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn // This is a local object... just call it directly. 164e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn try { 165e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn binder.dump(out, args); 166e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } catch (RemoteException e) { 167e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 168e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn return; 169e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 170e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 171850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey try (TransferPipe tp = new TransferPipe()) { 172e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn binder.dumpAsync(tp.getWriteFd().getFileDescriptor(), args); 173e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn tp.go(out, timeout); 174e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 175e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 176e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 177cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn public void go(FileDescriptor out) throws IOException { 178e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn go(out, DEFAULT_TIMEOUT); 179e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 180e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 181cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn public void go(FileDescriptor out, long timeout) throws IOException { 182e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn try { 183e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn synchronized (this) { 184e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mOutFd = out; 185e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mEndTime = SystemClock.uptimeMillis() + timeout; 186e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 187e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "read=" + getReadFd() + " write=" + getWriteFd() 188e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn + " out=" + out); 189e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 190e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn // Close the write fd, so we know when the other side is done. 191e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn closeFd(1); 192e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 193e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mThread.start(); 194e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 195e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn while (mFailure == null && !mComplete) { 196e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn long waitTime = mEndTime - SystemClock.uptimeMillis(); 197e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (waitTime <= 0) { 198e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "TIMEOUT!"); 199e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mThread.interrupt(); 200e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn throw new IOException("Timeout"); 201e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 202e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 203e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn try { 204e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn wait(waitTime); 205e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } catch (InterruptedException e) { 206e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 207e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 208e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 209e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "Finished: " + mFailure); 210e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (mFailure != null) { 211e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn throw new IOException(mFailure); 212e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 213e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 214e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } finally { 215e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn kill(); 216e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 217e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 218e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 219e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn void closeFd(int num) { 220e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (mFds[num] != null) { 221e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "Closing: " + mFds[num]); 222e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn try { 223e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mFds[num].close(); 224e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } catch (IOException e) { 225e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 226e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mFds[num] = null; 227e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 228e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 229e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 230850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey @Override 231850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey public void close() { 232850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey kill(); 233850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey } 234850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey 235cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn public void kill() { 2365ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan synchronized (this) { 2375ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan closeFd(0); 2385ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan closeFd(1); 2395ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan } 240e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 241e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 242983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams protected OutputStream getNewOutputStream() { 243983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams return new FileOutputStream(mOutFd); 244983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams } 245983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams 246e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn @Override 247e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn public void run() { 248e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn final byte[] buffer = new byte[1024]; 2495ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan final FileInputStream fis; 250983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams final OutputStream fos; 2515ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan 2525ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan synchronized (this) { 2535ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan ParcelFileDescriptor readFd = getReadFd(); 2545ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan if (readFd == null) { 2555ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan Slog.w(TAG, "Pipe has been closed..."); 2565ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan return; 2575ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan } 2585ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan fis = new FileInputStream(readFd.getFileDescriptor()); 259983829fec505c35b054c917668e9a54f2f4c26e4Kweku Adams fos = getNewOutputStream(); 2605ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan } 261e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 262e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "Ready to read pipe..."); 263e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn byte[] bufferPrefix = null; 264e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn boolean needPrefix = true; 265e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (mBufferPrefix != null) { 266e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn bufferPrefix = mBufferPrefix.getBytes(); 267e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 268e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 269e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn int size; 270e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn try { 271e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn while ((size=fis.read(buffer)) > 0) { 272e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "Got " + size + " bytes"); 273e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (bufferPrefix == null) { 274e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn fos.write(buffer, 0, size); 275e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } else { 276e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn int start = 0; 277e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn for (int i=0; i<size; i++) { 278e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (buffer[i] != '\n') { 279e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (i > start) { 280e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn fos.write(buffer, start, i-start); 281e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 282e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn start = i; 283e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (needPrefix) { 284e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn fos.write(bufferPrefix); 285e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn needPrefix = false; 286e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 287e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn do { 288e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn i++; 289e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } while (i<size && buffer[i] != '\n'); 290e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (i < size) { 291e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn needPrefix = true; 292e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 293e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 294e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 295e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (size > start) { 296e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn fos.write(buffer, start, size-start); 297e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 298e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 299e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 300e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "End of pipe: size=" + size); 301e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (mThread.isInterrupted()) { 302e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn if (DEBUG) Slog.i(TAG, "Interrupted!"); 303e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 304e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } catch (IOException e) { 305e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn synchronized (this) { 306e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mFailure = e.toString(); 307e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn notifyAll(); 308e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn return; 309e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 310e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 311e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 312e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn synchronized (this) { 313e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn mComplete = true; 314e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn notifyAll(); 315e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 316e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 317e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn} 318