ParcelFileDescriptorUtil.java

  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}