Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2015 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.mtp; |
| 18 | |
| 19 | import android.os.ParcelFileDescriptor; |
| 20 | import android.util.Log; |
| 21 | |
| 22 | import java.io.IOException; |
| 23 | import java.util.concurrent.ExecutorService; |
| 24 | import java.util.concurrent.Executors; |
Daichi Hirono | 24ab92a | 2016-03-04 17:53:03 +0900 | [diff] [blame] | 25 | import java.util.concurrent.TimeUnit; |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 26 | |
| 27 | class PipeManager { |
Daichi Hirono | 24ab92a | 2016-03-04 17:53:03 +0900 | [diff] [blame] | 28 | /** |
| 29 | * Milliseconds we wait for background thread when pausing. |
| 30 | */ |
| 31 | private final static long AWAIT_TERMINATION_TIMEOUT = 2000; |
| 32 | |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 33 | final ExecutorService mExecutor; |
Daichi Hirono | f578fa2 | 2016-02-19 18:05:42 +0900 | [diff] [blame] | 34 | final MtpDatabase mDatabase; |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 35 | |
Daichi Hirono | f578fa2 | 2016-02-19 18:05:42 +0900 | [diff] [blame] | 36 | PipeManager(MtpDatabase database) { |
| 37 | this(database, Executors.newSingleThreadExecutor()); |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 38 | } |
| 39 | |
Daichi Hirono | f578fa2 | 2016-02-19 18:05:42 +0900 | [diff] [blame] | 40 | PipeManager(MtpDatabase database, ExecutorService executor) { |
| 41 | this.mDatabase = database; |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 42 | this.mExecutor = executor; |
| 43 | } |
| 44 | |
Daichi Hirono | 3faa43a | 2015-08-05 17:15:35 +0900 | [diff] [blame] | 45 | ParcelFileDescriptor readDocument(MtpManager model, Identifier identifier) throws IOException { |
Tomasz Mikolajewski | 52652ac | 2015-08-05 17:33:33 +0900 | [diff] [blame] | 46 | final Task task = new ImportFileTask(model, identifier); |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 47 | mExecutor.execute(task); |
| 48 | return task.getReadingFileDescriptor(); |
| 49 | } |
| 50 | |
Daichi Hirono | 3faa43a | 2015-08-05 17:15:35 +0900 | [diff] [blame] | 51 | ParcelFileDescriptor readThumbnail(MtpManager model, Identifier identifier) throws IOException { |
| 52 | final Task task = new GetThumbnailTask(model, identifier); |
| 53 | mExecutor.execute(task); |
| 54 | return task.getReadingFileDescriptor(); |
| 55 | } |
| 56 | |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 57 | private static abstract class Task implements Runnable { |
Daichi Hirono | 2ff024f | 2015-08-11 20:02:58 +0900 | [diff] [blame] | 58 | protected final MtpManager mManager; |
Tomasz Mikolajewski | 52652ac | 2015-08-05 17:33:33 +0900 | [diff] [blame] | 59 | protected final Identifier mIdentifier; |
| 60 | protected final ParcelFileDescriptor[] mDescriptors; |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 61 | |
Daichi Hirono | 2ff024f | 2015-08-11 20:02:58 +0900 | [diff] [blame] | 62 | Task(MtpManager manager, Identifier identifier) throws IOException { |
| 63 | mManager = manager; |
Tomasz Mikolajewski | 52652ac | 2015-08-05 17:33:33 +0900 | [diff] [blame] | 64 | mIdentifier = identifier; |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 65 | mDescriptors = ParcelFileDescriptor.createReliablePipe(); |
| 66 | } |
| 67 | |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 68 | ParcelFileDescriptor getReadingFileDescriptor() { |
| 69 | return mDescriptors[0]; |
| 70 | } |
| 71 | } |
| 72 | |
Tomasz Mikolajewski | 52652ac | 2015-08-05 17:33:33 +0900 | [diff] [blame] | 73 | private static class ImportFileTask extends Task { |
| 74 | ImportFileTask(MtpManager model, Identifier identifier) throws IOException { |
| 75 | super(model, identifier); |
| 76 | } |
| 77 | |
| 78 | @Override |
| 79 | public void run() { |
| 80 | try { |
Daichi Hirono | 2ff024f | 2015-08-11 20:02:58 +0900 | [diff] [blame] | 81 | mManager.importFile( |
Daichi Hirono | 3faa43a | 2015-08-05 17:15:35 +0900 | [diff] [blame] | 82 | mIdentifier.mDeviceId, mIdentifier.mObjectHandle, mDescriptors[1]); |
Tomasz Mikolajewski | 52652ac | 2015-08-05 17:33:33 +0900 | [diff] [blame] | 83 | mDescriptors[1].close(); |
| 84 | } catch (IOException error) { |
| 85 | try { |
| 86 | mDescriptors[1].closeWithError("Failed to stream a file."); |
| 87 | } catch (IOException closeError) { |
| 88 | Log.w(MtpDocumentsProvider.TAG, closeError.getMessage()); |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | |
Daichi Hirono | 3faa43a | 2015-08-05 17:15:35 +0900 | [diff] [blame] | 94 | private static class GetThumbnailTask extends Task { |
| 95 | GetThumbnailTask(MtpManager model, Identifier identifier) throws IOException { |
| 96 | super(model, identifier); |
| 97 | } |
| 98 | |
| 99 | @Override |
| 100 | public void run() { |
| 101 | try { |
| 102 | try (final ParcelFileDescriptor.AutoCloseOutputStream stream = |
| 103 | new ParcelFileDescriptor.AutoCloseOutputStream(mDescriptors[1])) { |
| 104 | try { |
Daichi Hirono | 2ff024f | 2015-08-11 20:02:58 +0900 | [diff] [blame] | 105 | stream.write(mManager.getThumbnail( |
Daichi Hirono | 3faa43a | 2015-08-05 17:15:35 +0900 | [diff] [blame] | 106 | mIdentifier.mDeviceId, mIdentifier.mObjectHandle)); |
| 107 | } catch (IOException error) { |
| 108 | mDescriptors[1].closeWithError("Failed to stream a thumbnail."); |
| 109 | } |
| 110 | } |
| 111 | } catch (IOException closeError) { |
| 112 | Log.w(MtpDocumentsProvider.TAG, closeError.getMessage()); |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | |
Daichi Hirono | 24ab92a | 2016-03-04 17:53:03 +0900 | [diff] [blame] | 117 | boolean close() throws InterruptedException { |
| 118 | mExecutor.shutdownNow(); |
| 119 | return mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS); |
Daichi Hirono | 8ba4191 | 2015-07-30 21:22:57 +0900 | [diff] [blame] | 120 | } |
| 121 | } |