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