1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2009 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.provider;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.ContentProvider;
20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.ContentValues;
21476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Linimport android.content.Context;
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.database.Cursor;
23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.database.MatrixCursor;
24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.Uri;
25ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Linimport android.os.AsyncTask;
26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.Binder;
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.ParcelFileDescriptor;
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.provider.MediaStore.Images.ImageColumns;
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.util.Log;
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
316f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.app.GalleryApp;
32ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Linimport com.android.gallery3d.common.AsyncTaskUtil;
336f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.common.Utils;
346f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.DataManager;
356f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.MediaItem;
366f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.MediaObject;
376f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.data.Path;
386f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.picasasource.PicasaSource;
396f6230e40811effe0b0ca9ba023136b3b36130b7Owen Linimport com.android.gallery3d.util.GalleryUtils;
406f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.FileNotFoundException;
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.IOException;
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class GalleryProvider extends ContentProvider {
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "GalleryProvider";
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
47cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen    public static final String AUTHORITY = "com.android.gallery3d.provider";
48cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen    public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY);
496f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin
506f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin    public static interface PicasaColumns {
516f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin        public static final String USER_ACCOUNT = "user_account";
526f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin        public static final String PICASA_ID = "picasa_id";
536f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin    }
546f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin
55cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen    private static final String[] SUPPORTED_PICASA_COLUMNS = {
566f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin            PicasaColumns.USER_ACCOUNT,
576f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin            PicasaColumns.PICASA_ID,
58cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen            ImageColumns.DISPLAY_NAME,
59cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen            ImageColumns.SIZE,
60cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen            ImageColumns.MIME_TYPE,
61cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen            ImageColumns.DATE_TAKEN,
62cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen            ImageColumns.LATITUDE,
63cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen            ImageColumns.LONGITUDE,
64cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen            ImageColumns.ORIENTATION};
65cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private DataManager mDataManager;
67476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin    private static Uri sBaseUri;
68476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin
69476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin    public static String getAuthority(Context context) {
70476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin        return context.getPackageName() + ".provider";
71476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin    }
72476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin
73476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin    public static Uri getUriFor(Context context, Path path) {
74476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin        if (sBaseUri == null) {
75476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin            sBaseUri = Uri.parse("content://" + context.getPackageName() + ".provider");
76476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin        }
77476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin        return sBaseUri.buildUpon()
78476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin                .appendEncodedPath(path.toString().substring(1)) // ignore the leading '/'
79476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin                .build();
80476a89e18fc6b8a472b4e352d20be3a09a1776a4Owen Lin    }
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int delete(Uri uri, String selection, String[] selectionArgs) {
84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        throw new UnsupportedOperationException();
85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // TODO: consider concurrent access
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public String getType(Uri uri) {
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        long token = Binder.clearCallingIdentity();
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        try {
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Path path = Path.fromString(uri.getPath());
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            MediaItem item = (MediaItem) mDataManager.getMediaObject(path);
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return item != null ? item.getMimeType() : null;
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } finally {
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Binder.restoreCallingIdentity(token);
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public Uri insert(Uri uri, ContentValues values) {
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        throw new UnsupportedOperationException();
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public boolean onCreate() {
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        GalleryApp app = (GalleryApp) getContext().getApplicationContext();
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mDataManager = app.getDataManager();
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return true;
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // TODO: consider concurrent access
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public Cursor query(Uri uri, String[] projection,
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            String selection, String[] selectionArgs, String sortOrder) {
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        long token = Binder.clearCallingIdentity();
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        try {
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Path path = Path.fromString(uri.getPath());
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            MediaObject object = mDataManager.getMediaObject(path);
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (object == null) {
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                Log.w(TAG, "cannot find: " + uri);
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return null;
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (PicasaSource.isPicasaImage(object)) {
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return queryPicasaItem(object,
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        projection, selection, selectionArgs, sortOrder);
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    return null;
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } finally {
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Binder.restoreCallingIdentity(token);
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Cursor queryPicasaItem(MediaObject image, String[] projection,
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            String selection, String[] selectionArgs, String sortOrder) {
137cd09872e859075aa8b5b90a151b0cae901bf4810Ray Chen        if (projection == null) projection = SUPPORTED_PICASA_COLUMNS;
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Object[] columnValues = new Object[projection.length];
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        double latitude = PicasaSource.getLatitude(image);
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        double longitude = PicasaSource.getLongitude(image);
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        boolean isValidLatlong = GalleryUtils.isValidLocation(latitude, longitude);
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0, n = projection.length; i < n; ++i) {
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            String column = projection[i];
1456f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin            if (PicasaColumns.USER_ACCOUNT.equals(column)) {
1466f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin                columnValues[i] = PicasaSource.getUserAccount(getContext(), image);
1476f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin            } else if (PicasaColumns.PICASA_ID.equals(column)) {
1486f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin                columnValues[i] = PicasaSource.getPicasaId(image);
1496f6230e40811effe0b0ca9ba023136b3b36130b7Owen Lin            } else if (ImageColumns.DISPLAY_NAME.equals(column)) {
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                columnValues[i] = PicasaSource.getImageTitle(image);
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (ImageColumns.SIZE.equals(column)){
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                columnValues[i] = PicasaSource.getImageSize(image);
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (ImageColumns.MIME_TYPE.equals(column)) {
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                columnValues[i] = PicasaSource.getContentType(image);
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (ImageColumns.DATE_TAKEN.equals(column)) {
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                columnValues[i] = PicasaSource.getDateTaken(image);
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (ImageColumns.LATITUDE.equals(column)) {
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                columnValues[i] = isValidLatlong ? latitude : null;
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (ImageColumns.LONGITUDE.equals(column)) {
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                columnValues[i] = isValidLatlong ? longitude : null;
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (ImageColumns.ORIENTATION.equals(column)) {
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                columnValues[i] = PicasaSource.getRotation(image);
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                Log.w(TAG, "unsupported column: " + column);
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        MatrixCursor cursor = new MatrixCursor(projection);
168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        cursor.addRow(columnValues);
169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return cursor;
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public ParcelFileDescriptor openFile(Uri uri, String mode)
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            throws FileNotFoundException {
175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        long token = Binder.clearCallingIdentity();
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        try {
177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mode.contains("w")) {
178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                throw new FileNotFoundException("cannot open file for write");
179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Path path = Path.fromString(uri.getPath());
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            MediaObject object = mDataManager.getMediaObject(path);
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (object == null) {
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                throw new FileNotFoundException(uri.toString());
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (PicasaSource.isPicasaImage(object)) {
186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return PicasaSource.openFile(getContext(), object, mode);
187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                throw new FileNotFoundException("unspported type: " + object);
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } finally {
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Binder.restoreCallingIdentity(token);
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        throw new UnsupportedOperationException();
198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
200ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin    private static interface PipeDataWriter<T> {
201ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin        void writeDataToPipe(ParcelFileDescriptor output, T args);
202ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin    }
203ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin
204ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin    // Modified from ContentProvider.openPipeHelper. We are target at API LEVEL 10.
205ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin    // But openPipeHelper is available in API LEVEL 11.
206ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin    private static <T> ParcelFileDescriptor openPipeHelper(
207ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin            final T args, final PipeDataWriter<T> func) throws FileNotFoundException {
208ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin        try {
209ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin            final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
210ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin            AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() {
211ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                @Override
212ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                protected Object doInBackground(Object... params) {
213ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                    try {
214ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                        func.writeDataToPipe(pipe[1], args);
215ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                        return null;
216ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                    } finally {
217ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                        Utils.closeSilently(pipe[1]);
218ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                    }
219ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin                }
220ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin            };
221ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin            AsyncTaskUtil.executeInParallel(task, (Object[]) null);
222ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin            return pipe[0];
223ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin        } catch (IOException e) {
224ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin            throw new FileNotFoundException("failure making pipe");
225ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin        }
226ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin    }
227ed97d58f2028938aeb3e49c10ac598cc3e7a28c6Owen Lin
228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
229