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
19850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkeyimport java.io.Closeable;
20e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport java.io.FileDescriptor;
21e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport java.io.FileInputStream;
22e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport java.io.FileOutputStream;
23e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport java.io.IOException;
24e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
25e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.Binder;
26e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.IBinder;
27e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.IInterface;
28e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.ParcelFileDescriptor;
29e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.RemoteException;
30e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.os.SystemClock;
31e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackbornimport android.util.Slog;
32e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
33e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn/**
34e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * Helper for transferring data through a pipe from a client app.
35e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn */
36850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkeypublic final class TransferPipe implements Runnable, Closeable {
37e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    static final String TAG = "TransferPipe";
38e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    static final boolean DEBUG = false;
39e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
40e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    static final long DEFAULT_TIMEOUT = 5000;  // 5 seconds
41e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
42850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    final Thread mThread;
43e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    final ParcelFileDescriptor[] mFds;
44e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
45e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    FileDescriptor mOutFd;
46e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    long mEndTime;
47e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    String mFailure;
48e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    boolean mComplete;
49e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
50e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    String mBufferPrefix;
51e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
52e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    interface Caller {
53e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        void go(IInterface iface, FileDescriptor fd, String prefix,
54e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                String[] args) throws RemoteException;
55e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
56e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
57cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn    public TransferPipe() throws IOException {
58850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey        this(null);
59850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    }
60850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey
61850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    public TransferPipe(String bufferPrefix) throws IOException {
62e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        mThread = new Thread(this, "TransferPipe");
63e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        mFds = ParcelFileDescriptor.createPipe();
64850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey        mBufferPrefix = bufferPrefix;
65e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
66e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
67e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    ParcelFileDescriptor getReadFd() {
68e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        return mFds[0];
69e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
70e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
71cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn    public ParcelFileDescriptor getWriteFd() {
72e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        return mFds[1];
73e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
74e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
75cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn    public void setBufferPrefix(String prefix) {
76e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        mBufferPrefix = prefix;
77e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
78e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
79850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    public static void dumpAsync(IBinder binder, FileDescriptor out, String[] args)
80850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey            throws IOException, RemoteException {
81850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey        goDump(binder, out, args);
82850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    }
83850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey
84e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    static void go(Caller caller, IInterface iface, FileDescriptor out,
85e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            String prefix, String[] args) throws IOException, RemoteException {
86e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        go(caller, iface, out, prefix, args, DEFAULT_TIMEOUT);
87e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
88e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
89e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    static void go(Caller caller, IInterface iface, FileDescriptor out,
90e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            String prefix, String[] args, long timeout) throws IOException, RemoteException {
91e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        if ((iface.asBinder()) instanceof Binder) {
92e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            // This is a local object...  just call it directly.
93e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            try {
94e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                caller.go(iface, out, prefix, args);
95e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            } catch (RemoteException e) {
96e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            }
97e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            return;
98e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
99e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
100850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey        try (TransferPipe tp = new TransferPipe()) {
101e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            caller.go(iface, tp.getWriteFd().getFileDescriptor(), prefix, args);
102e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            tp.go(out, timeout);
103e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
104e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
105e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
106e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    static void goDump(IBinder binder, FileDescriptor out,
107e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            String[] args) throws IOException, RemoteException {
108e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        goDump(binder, out, args, DEFAULT_TIMEOUT);
109e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
110e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
111e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    static void goDump(IBinder binder, FileDescriptor out,
112e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            String[] args, long timeout) throws IOException, RemoteException {
113e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        if (binder instanceof Binder) {
114e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            // This is a local object...  just call it directly.
115e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            try {
116e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                binder.dump(out, args);
117e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            } catch (RemoteException e) {
118e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            }
119e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            return;
120e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
121e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
122850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey        try (TransferPipe tp = new TransferPipe()) {
123e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            binder.dumpAsync(tp.getWriteFd().getFileDescriptor(), args);
124e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            tp.go(out, timeout);
125e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
126e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
127e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
128cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn    public void go(FileDescriptor out) throws IOException {
129e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        go(out, DEFAULT_TIMEOUT);
130e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
131e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
132cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn    public void go(FileDescriptor out, long timeout) throws IOException {
133e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        try {
134e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            synchronized (this) {
135e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                mOutFd = out;
136e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                mEndTime = SystemClock.uptimeMillis() + timeout;
137e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
138e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                if (DEBUG) Slog.i(TAG, "read=" + getReadFd() + " write=" + getWriteFd()
139e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        + " out=" + out);
140e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
141e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                // Close the write fd, so we know when the other side is done.
142e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                closeFd(1);
143e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
144e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                mThread.start();
145e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
146e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                while (mFailure == null && !mComplete) {
147e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    long waitTime = mEndTime - SystemClock.uptimeMillis();
148e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    if (waitTime <= 0) {
149e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        if (DEBUG) Slog.i(TAG, "TIMEOUT!");
150e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        mThread.interrupt();
151e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        throw new IOException("Timeout");
152e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    }
153e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
154e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    try {
155e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        wait(waitTime);
156e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    } catch (InterruptedException e) {
157e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    }
158e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                }
159e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
160e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                if (DEBUG) Slog.i(TAG, "Finished: " + mFailure);
161e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                if (mFailure != null) {
162e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    throw new IOException(mFailure);
163e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                }
164e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            }
165e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        } finally {
166e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            kill();
167e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
168e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
169e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
170e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    void closeFd(int num) {
171e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        if (mFds[num] != null) {
172e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            if (DEBUG) Slog.i(TAG, "Closing: " + mFds[num]);
173e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            try {
174e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                mFds[num].close();
175e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            } catch (IOException e) {
176e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            }
177e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            mFds[num] = null;
178e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
179e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
180e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
181850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    @Override
182850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    public void close() {
183850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey        kill();
184850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey    }
185850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey
186cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn    public void kill() {
1875ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan        synchronized (this) {
1885ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan            closeFd(0);
1895ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan            closeFd(1);
1905ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan        }
191e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
192e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
193e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    @Override
194e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    public void run() {
195e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        final byte[] buffer = new byte[1024];
1965ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan        final FileInputStream fis;
1975ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan        final FileOutputStream fos;
1985ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan
1995ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan        synchronized (this) {
2005ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan            ParcelFileDescriptor readFd = getReadFd();
2015ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan            if (readFd == null) {
2025ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan                Slog.w(TAG, "Pipe has been closed...");
2035ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan                return;
2045ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan            }
2055ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan            fis = new FileInputStream(readFd.getFileDescriptor());
2065ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan            fos = new FileOutputStream(mOutFd);
2075ec679a0fa2e26c058a8094836d80e4e989f74d5Xin Guan        }
208e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
209e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        if (DEBUG) Slog.i(TAG, "Ready to read pipe...");
210e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        byte[] bufferPrefix = null;
211e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        boolean needPrefix = true;
212e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        if (mBufferPrefix != null) {
213e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            bufferPrefix = mBufferPrefix.getBytes();
214e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
215e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
216e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        int size;
217e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        try {
218e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            while ((size=fis.read(buffer)) > 0) {
219e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                if (DEBUG) Slog.i(TAG, "Got " + size + " bytes");
220e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                if (bufferPrefix == null) {
221e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    fos.write(buffer, 0, size);
222e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                } else {
223e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    int start = 0;
224e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    for (int i=0; i<size; i++) {
225e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        if (buffer[i] != '\n') {
226e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            if (i > start) {
227e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                                fos.write(buffer, start, i-start);
228e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            }
229e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            start = i;
230e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            if (needPrefix) {
231e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                                fos.write(bufferPrefix);
232e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                                needPrefix = false;
233e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            }
234e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            do {
235e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                                i++;
236e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            } while (i<size && buffer[i] != '\n');
237e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            if (i < size) {
238e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                                needPrefix = true;
239e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                            }
240e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        }
241e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    }
242e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    if (size > start) {
243e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                        fos.write(buffer, start, size-start);
244e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                    }
245e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                }
246e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            }
247e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            if (DEBUG) Slog.i(TAG, "End of pipe: size=" + size);
248e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            if (mThread.isInterrupted()) {
249e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                if (DEBUG) Slog.i(TAG, "Interrupted!");
250e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            }
251e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        } catch (IOException e) {
252e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            synchronized (this) {
253e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                mFailure = e.toString();
254e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                notifyAll();
255e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn                return;
256e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            }
257e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
258e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn
259e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        synchronized (this) {
260e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            mComplete = true;
261e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn            notifyAll();
262e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn        }
263e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn    }
264e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn}
265