Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java

Issue 2948583002: Photo Picker dialog: Convert to AIDL for easier security review. (Closed)
Patch Set: Adding to owners file Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.photo_picker; 5 package org.chromium.chrome.browser.photo_picker;
6 6
7 import android.content.ComponentName; 7 import android.content.ComponentName;
8 import android.content.Context; 8 import android.content.Context;
9 import android.content.Intent; 9 import android.content.Intent;
10 import android.content.ServiceConnection; 10 import android.content.ServiceConnection;
11 import android.graphics.Bitmap; 11 import android.graphics.Bitmap;
12 import android.os.Bundle; 12 import android.os.Bundle;
13 import android.os.Handler;
14 import android.os.IBinder; 13 import android.os.IBinder;
15 import android.os.Message; 14 import android.os.Message;
16 import android.os.Messenger;
17 import android.os.ParcelFileDescriptor; 15 import android.os.ParcelFileDescriptor;
18 import android.os.RemoteException; 16 import android.os.RemoteException;
19 import android.os.StrictMode; 17 import android.os.StrictMode;
20 import android.os.SystemClock; 18 import android.os.SystemClock;
21 19
22 import org.chromium.base.Log; 20 import org.chromium.base.Log;
21 import org.chromium.base.ThreadUtils;
23 import org.chromium.base.metrics.RecordHistogram; 22 import org.chromium.base.metrics.RecordHistogram;
24 import org.chromium.chrome.browser.util.ConversionUtils; 23 import org.chromium.chrome.browser.util.ConversionUtils;
25 24
26 import java.io.File; 25 import java.io.File;
27 import java.io.FileDescriptor; 26 import java.io.FileDescriptor;
28 import java.io.FileInputStream; 27 import java.io.FileInputStream;
29 import java.io.IOException; 28 import java.io.IOException;
30 import java.lang.ref.WeakReference;
31 import java.util.LinkedHashMap; 29 import java.util.LinkedHashMap;
32 import java.util.concurrent.TimeUnit; 30 import java.util.concurrent.TimeUnit;
33 31
34 /** 32 /**
35 * A class to communicate with the {@link DecoderService}. 33 * A class to communicate with the {@link DecoderService}.
36 */ 34 */
37 public class DecoderServiceHost { 35 public class DecoderServiceHost extends IDecoderServiceCallback.Stub {
38 // A tag for logging error messages. 36 // A tag for logging error messages.
39 private static final String TAG = "ImageDecoderHost"; 37 private static final String TAG = "ImageDecoderHost";
40 38
39 IDecoderService mIRemoteService;
40 private ServiceConnection mConnection = new ServiceConnection() {
41 public void onServiceConnected(ComponentName className, IBinder service) {
42 mIRemoteService = IDecoderService.Stub.asInterface(service);
43 mBound = true;
44 mCallback.serviceReady();
45 }
46
47 public void onServiceDisconnected(ComponentName className) {
48 Log.e(TAG, "Service has unexpectedly disconnected");
49 mIRemoteService = null;
50 mBound = false;
51 }
52 };
53
41 /** 54 /**
42 * Interface for notifying clients of the service being ready. 55 * Interface for notifying clients of the service being ready.
43 */ 56 */
44 public interface ServiceReadyCallback { 57 public interface ServiceReadyCallback {
45 /** 58 /**
46 * A function to define to receive a notification once the service is up and running. 59 * A function to define to receive a notification once the service is up and running.
47 */ 60 */
48 void serviceReady(); 61 void serviceReady();
49 } 62 }
50 63
51 /** 64 /**
52 * An interface notifying clients when an image has finished decoding. 65 * An interface notifying clients when an image has finished decoding.
53 */ 66 */
54 public interface ImageDecodedCallback { 67 public interface ImageDecodedCallback {
55 /** 68 /**
56 * A function to define to receive a notification that an image has been decoded. 69 * A function to define to receive a notification that an image has been decoded.
57 * @param filePath The file path for the newly decoded image. 70 * @param filePath The file path for the newly decoded image.
58 * @param bitmap The results of the decoding (or placeholder image, if f ailed). 71 * @param bitmap The results of the decoding (or placeholder image, if f ailed).
59 */ 72 */
60 void imageDecodedCallback(String filePath, Bitmap bitmap); 73 void imageDecodedCallback(String filePath, Bitmap bitmap);
61 } 74 }
62 75
63 /** 76 /**
64 * Class for interacting with the main interface of the service.
65 */
66 private class DecoderServiceConnection implements ServiceConnection {
67 // The callback to use to notify the service being ready.
68 private ServiceReadyCallback mCallback;
69
70 public DecoderServiceConnection(ServiceReadyCallback callback) {
71 mCallback = callback;
72 }
73
74 // Called when a connection to the service has been established.
75 public void onServiceConnected(ComponentName name, IBinder service) {
76 mService = new Messenger(service);
77 mBound = true;
78 mCallback.serviceReady();
79 }
80
81 // Called when a connection to the service has been lost.
82 public void onServiceDisconnected(ComponentName name) {
83 mBound = false;
84 }
85 }
86
87 /**
88 * Class for keeping track of the data involved with each request. 77 * Class for keeping track of the data involved with each request.
89 */ 78 */
90 private static class DecoderServiceParams { 79 private static class DecoderServiceParams {
91 // The path to the file containing the bitmap to decode. 80 // The path to the file containing the bitmap to decode.
92 public String mFilePath; 81 public String mFilePath;
93 82
94 // The requested size (width and height) of the bitmap, once decoded. 83 // The requested size (width and height) of the bitmap, once decoded.
95 public int mSize; 84 public int mSize;
96 85
97 // The callback to use to communicate the results of the decoding. 86 // The callback to use to communicate the results of the decoding.
(...skipping 11 matching lines...) Expand all
109 98
110 // Map of file paths to decoder parameters in order of request. 99 // Map of file paths to decoder parameters in order of request.
111 private LinkedHashMap<String, DecoderServiceParams> mRequests = new LinkedHa shMap<>(); 100 private LinkedHashMap<String, DecoderServiceParams> mRequests = new LinkedHa shMap<>();
112 LinkedHashMap<String, DecoderServiceParams> getRequests() { 101 LinkedHashMap<String, DecoderServiceParams> getRequests() {
113 return mRequests; 102 return mRequests;
114 } 103 }
115 104
116 // The callback used to notify the client when the service is ready. 105 // The callback used to notify the client when the service is ready.
117 private ServiceReadyCallback mCallback; 106 private ServiceReadyCallback mCallback;
118 107
119 // Messenger for communicating with the remote service.
120 Messenger mService = null;
121
122 // Our service connection to the {@link DecoderService}.
123 private DecoderServiceConnection mConnection;
124
125 // Flag indicating whether we are bound to the service. 108 // Flag indicating whether we are bound to the service.
126 boolean mBound; 109 boolean mBound;
127 110
128 // The inbound messenger used by the remote service to communicate with us. 111 private Context mContext;
129 final Messenger mMessenger = new Messenger(new IncomingHandler(this));
130 112
131 /** 113 /**
132 * The DecoderServiceHost constructor. 114 * The DecoderServiceHost constructor.
133 * @param callback The callback to use when communicating back to the client . 115 * @param callback The callback to use when communicating back to the client .
134 */ 116 */
135 public DecoderServiceHost(ServiceReadyCallback callback) { 117 public DecoderServiceHost(ServiceReadyCallback callback, Context context) {
136 mCallback = callback; 118 mCallback = callback;
119 mContext = context;
137 } 120 }
138 121
139 /** 122 /**
140 * Initiate binding with the {@link DecoderService}. 123 * Initiate binding with the {@link DecoderService}.
141 * @param context The context to use. 124 * @param context The context to use.
142 */ 125 */
143 public void bind(Context context) { 126 public void bind(Context context) {
144 mConnection = new DecoderServiceConnection(mCallback); 127 Intent intent = new Intent(mContext, DecoderService.class);
145 Intent intent = new Intent(context, DecoderService.class); 128 intent.setAction(IDecoderService.class.getName());
146 context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 129 mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
147 } 130 }
148 131
149 /** 132 /**
150 * Unbind from the {@link DecoderService}. 133 * Unbind from the {@link DecoderService}.
151 * @param context The context to use. 134 * @param context The context to use.
152 */ 135 */
153 public void unbind(Context context) { 136 public void unbind(Context context) {
154 if (mBound) { 137 if (mBound) {
155 context.unbindService(mConnection); 138 context.unbindService(mConnection);
156 mBound = false; 139 mBound = false;
(...skipping 17 matching lines...) Expand all
174 * Dispatches the next image for decoding (from the queue). 157 * Dispatches the next image for decoding (from the queue).
175 */ 158 */
176 private void dispatchNextDecodeImageRequest() { 159 private void dispatchNextDecodeImageRequest() {
177 if (mRequests.entrySet().iterator().hasNext()) { 160 if (mRequests.entrySet().iterator().hasNext()) {
178 DecoderServiceParams params = mRequests.entrySet().iterator().next() .getValue(); 161 DecoderServiceParams params = mRequests.entrySet().iterator().next() .getValue();
179 params.mTimestamp = SystemClock.elapsedRealtime(); 162 params.mTimestamp = SystemClock.elapsedRealtime();
180 dispatchDecodeImageRequest(params.mFilePath, params.mSize); 163 dispatchDecodeImageRequest(params.mFilePath, params.mSize);
181 } 164 }
182 } 165 }
183 166
167 @Override
168 public void onDecodeImageDone(final Bundle payload) {
169 ThreadUtils.runOnUiThread(new Runnable() {
170 @Override
171 public void run() {
172 // Read the reply back from the service.
173 String filePath = payload.getString(DecoderService.KEY_FILE_PATH );
174 Boolean success = payload.getBoolean(DecoderService.KEY_SUCCESS) ;
175 Bitmap bitmap = success
176 ? (Bitmap) payload.getParcelable(DecoderService.KEY_IMAG E_BITMAP)
177 : null;
178 long decodeTime = payload.getLong(DecoderService.KEY_DECODE_TIME );
179 closeRequest(filePath, bitmap, decodeTime);
180 }
181 });
182 }
183
184 /** 184 /**
185 * Ties up all the loose ends from the decoding request (communicates the re sults of the 185 * Ties up all the loose ends from the decoding request (communicates the re sults of the
186 * decoding process back to the client, and takes care of house-keeping chor es regarding 186 * decoding process back to the client, and takes care of house-keeping chor es regarding
187 * the request queue). 187 * the request queue).
188 * @param filePath The path to the image that was just decoded. 188 * @param filePath The path to the image that was just decoded.
189 * @param bitmap The resulting decoded bitmap. 189 * @param bitmap The resulting decoded bitmap.
190 * @param decodeTime The length of time it took to decode the bitmap. 190 * @param decodeTime The length of time it took to decode the bitmap.
191 */ 191 */
192 public void closeRequest(String filePath, Bitmap bitmap, long decodeTime) { 192 public void closeRequest(String filePath, Bitmap bitmap, long decodeTime) {
193 DecoderServiceParams params = getRequests().get(filePath); 193 DecoderServiceParams params = getRequests().get(filePath);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 if (inputFile != null) inputFile.close(); 241 if (inputFile != null) inputFile.close();
242 } catch (IOException e) { 242 } catch (IOException e) {
243 Log.e(TAG, "Unable to close inputFile: " + e); 243 Log.e(TAG, "Unable to close inputFile: " + e);
244 } 244 }
245 StrictMode.setThreadPolicy(oldPolicy); 245 StrictMode.setThreadPolicy(oldPolicy);
246 } 246 }
247 247
248 if (pfd == null) return; 248 if (pfd == null) return;
249 249
250 // Prepare and send the data over. 250 // Prepare and send the data over.
251 Message payload = Message.obtain(null, DecoderService.MSG_DECODE_IMAGE); 251 Message payload = Message.obtain();
Theresa 2017/06/20 15:11:56 Is payload used anymore?
Finnur 2017/06/20 15:49:16 No. Good catch.
252 payload.replyTo = mMessenger;
253 bundle.putString(DecoderService.KEY_FILE_PATH, filePath); 252 bundle.putString(DecoderService.KEY_FILE_PATH, filePath);
254 bundle.putInt(DecoderService.KEY_SIZE, size); 253 bundle.putInt(DecoderService.KEY_SIZE, size);
255 payload.setData(bundle); 254 payload.setData(bundle);
256 try { 255 try {
257 mService.send(payload); 256 mIRemoteService.decodeImage(bundle, this);
258 pfd.close(); 257 pfd.close();
259 } catch (RemoteException e) { 258 } catch (RemoteException e) {
260 Log.e(TAG, "Communications failed (Remote): " + e); 259 Log.e(TAG, "Communications failed (Remote): " + e);
261 closeRequest(filePath, null, -1); 260 closeRequest(filePath, null, -1);
262 } catch (IOException e) { 261 } catch (IOException e) {
263 Log.e(TAG, "Communications failed (IO): " + e); 262 Log.e(TAG, "Communications failed (IO): " + e);
264 closeRequest(filePath, null, -1); 263 closeRequest(filePath, null, -1);
265 } 264 }
266 } 265 }
267 266
268 /** 267 /**
269 * Cancels a request to decode an image (if it hasn't already been dispatche d). 268 * Cancels a request to decode an image (if it hasn't already been dispatche d).
270 * @param filePath The path to the image to cancel decoding. 269 * @param filePath The path to the image to cancel decoding.
271 */ 270 */
272 public void cancelDecodeImage(String filePath) { 271 public void cancelDecodeImage(String filePath) {
273 mRequests.remove(filePath); 272 mRequests.remove(filePath);
274 } 273 }
275
276 /**
277 * A class for handling communications from the service to us.
278 */
279 static class IncomingHandler extends Handler {
280 // The DecoderServiceHost object to communicate with.
281 private final WeakReference<DecoderServiceHost> mHost;
282
283 /**
284 * Constructor for IncomingHandler.
285 * @param host The DecoderServiceHost object to communicate with.
286 */
287 IncomingHandler(DecoderServiceHost host) {
288 mHost = new WeakReference<DecoderServiceHost>(host);
289 }
290
291 @Override
292 public void handleMessage(Message msg) {
293 DecoderServiceHost host = mHost.get();
294 if (host == null) {
295 super.handleMessage(msg);
296 return;
297 }
298
299 switch (msg.what) {
300 case DecoderService.MSG_IMAGE_DECODED_REPLY:
301 Bundle payload = msg.getData();
302
303 // Read the reply back from the service.
304 String filePath = payload.getString(DecoderService.KEY_FILE_ PATH);
305 Boolean success = payload.getBoolean(DecoderService.KEY_SUCC ESS);
306 Bitmap bitmap = success
307 ? (Bitmap) payload.getParcelable(DecoderService.KEY_ IMAGE_BITMAP)
308 : null;
309 long decodeTime = payload.getLong(DecoderService.KEY_DECODE_ TIME);
310 host.closeRequest(filePath, bitmap, decodeTime);
311 break;
312 default:
313 super.handleMessage(msg);
314 }
315 }
316 }
317 } 274 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698