1/*
2 * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
3 * 2013 Florian Schmaus <flo@geekplace.eu>
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.openintents.openpgp.util;
19
20import android.os.ParcelFileDescriptor;
21
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.OutputStream;
25
26/**
27 * Partially based on <a href="http://stackoverflow.com/questions/18212152/">Stackoverflow: Transfer InputStream to another Service (across process boundaries)</a>
28 **/
29public class ParcelFileDescriptorUtil {
30
31 public interface IThreadListener {
32 void onThreadFinished(final Thread thread);
33 }
34
35 public static ParcelFileDescriptor pipeFrom(InputStream inputStream, IThreadListener listener)
36 throws IOException {
37 ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
38 ParcelFileDescriptor readSide = pipe[0];
39 ParcelFileDescriptor writeSide = pipe[1];
40
41 // start the transfer thread
42 new TransferThread(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide),
43 listener)
44 .start();
45
46 return readSide;
47 }
48
49 public static ParcelFileDescriptor pipeTo(OutputStream outputStream, IThreadListener listener)
50 throws IOException {
51 ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
52 ParcelFileDescriptor readSide = pipe[0];
53 ParcelFileDescriptor writeSide = pipe[1];
54
55 // start the transfer thread
56 new TransferThread(new ParcelFileDescriptor.AutoCloseInputStream(readSide), outputStream,
57 listener)
58 .start();
59
60 return writeSide;
61 }
62
63 static class TransferThread extends Thread {
64 final InputStream mIn;
65 final OutputStream mOut;
66 final IThreadListener mListener;
67
68 TransferThread(InputStream in, OutputStream out, IThreadListener listener) {
69 super("ParcelFileDescriptor Transfer Thread");
70 mIn = in;
71 mOut = out;
72 mListener = listener;
73 setDaemon(true);
74 }
75
76 @Override
77 public void run() {
78 byte[] buf = new byte[1024];
79 int len;
80
81 try {
82 while ((len = mIn.read(buf)) > 0) {
83 mOut.write(buf, 0, len);
84 }
85 mOut.flush(); // just to be safe
86 } catch (IOException e) {
87 //Log.e(OpenPgpApi.TAG, "TransferThread" + getId() + ": writing failed", e);
88 } finally {
89 try {
90 mIn.close();
91 } catch (IOException e) {
92 //Log.e(OpenPgpApi.TAG, "TransferThread" + getId(), e);
93 }
94 try {
95 mOut.close();
96 } catch (IOException e) {
97 //Log.e(OpenPgpApi.TAG, "TransferThread" + getId(), e);
98 }
99 }
100 if (mListener != null) {
101 //Log.d(OpenPgpApi.TAG, "TransferThread " + getId() + " finished!");
102 mListener.onThreadFinished(this);
103 }
104 }
105 }
106}