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

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

Issue 2915863002: Photo Picker dialog: Add UMA statistics. (Closed)
Patch Set: 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; 13 import android.os.Handler;
14 import android.os.IBinder; 14 import android.os.IBinder;
15 import android.os.Message; 15 import android.os.Message;
16 import android.os.Messenger; 16 import android.os.Messenger;
17 import android.os.ParcelFileDescriptor; 17 import android.os.ParcelFileDescriptor;
18 import android.os.RemoteException; 18 import android.os.RemoteException;
19 import android.os.StrictMode; 19 import android.os.StrictMode;
20 import android.os.SystemClock;
20 21
21 import org.chromium.base.Log; 22 import org.chromium.base.Log;
23 import org.chromium.base.metrics.RecordHistogram;
22 24
23 import java.io.File; 25 import java.io.File;
24 import java.io.FileDescriptor; 26 import java.io.FileDescriptor;
25 import java.io.FileInputStream; 27 import java.io.FileInputStream;
26 import java.io.IOException; 28 import java.io.IOException;
27 import java.lang.ref.WeakReference; 29 import java.lang.ref.WeakReference;
28 import java.util.LinkedHashMap; 30 import java.util.LinkedHashMap;
31 import java.util.concurrent.TimeUnit;
29 32
30 /** 33 /**
31 * A class to communicate with the {@link DecoderService}. 34 * A class to communicate with the {@link DecoderService}.
32 */ 35 */
33 public class DecoderServiceHost { 36 public class DecoderServiceHost {
34 // A tag for logging error messages. 37 // A tag for logging error messages.
35 private static final String TAG = "ImageDecoderHost"; 38 private static final String TAG = "ImageDecoderHost";
36 39
37 /** 40 /**
38 * Interface for notifying clients of the service being ready. 41 * Interface for notifying clients of the service being ready.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 private static class DecoderServiceParams { 89 private static class DecoderServiceParams {
87 // The path to the file containing the bitmap to decode. 90 // The path to the file containing the bitmap to decode.
88 public String mFilePath; 91 public String mFilePath;
89 92
90 // The requested size (width and height) of the bitmap, once decoded. 93 // The requested size (width and height) of the bitmap, once decoded.
91 public int mSize; 94 public int mSize;
92 95
93 // The callback to use to communicate the results of the decoding. 96 // The callback to use to communicate the results of the decoding.
94 ImageDecodedCallback mCallback; 97 ImageDecodedCallback mCallback;
95 98
99 // The timestamp for when the request is being sent over for decoding.
Theresa 2017/05/31 18:40:02 nit: ...when the request was sent..
Finnur 2017/06/01 15:13:55 Done.
100 long mTimestamp;
101
96 public DecoderServiceParams(String filePath, int size, ImageDecodedCallb ack callback) { 102 public DecoderServiceParams(String filePath, int size, ImageDecodedCallb ack callback) {
97 mFilePath = filePath; 103 mFilePath = filePath;
98 mSize = size; 104 mSize = size;
99 mCallback = callback; 105 mCallback = callback;
100 } 106 }
101 } 107 }
102 108
103 // Map of file paths to decoder parameters in order of request. 109 // Map of file paths to decoder parameters in order of request.
104 private LinkedHashMap<String, DecoderServiceParams> mRequests = new LinkedHa shMap<>(); 110 private LinkedHashMap<String, DecoderServiceParams> mRequests = new LinkedHa shMap<>();
105 LinkedHashMap<String, DecoderServiceParams> getRequests() { 111 LinkedHashMap<String, DecoderServiceParams> getRequests() {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 mRequests.put(filePath, params); 168 mRequests.put(filePath, params);
163 if (mRequests.size() == 1) dispatchNextDecodeImageRequest(); 169 if (mRequests.size() == 1) dispatchNextDecodeImageRequest();
164 } 170 }
165 171
166 /** 172 /**
167 * Dispatches the next image for decoding (from the queue). 173 * Dispatches the next image for decoding (from the queue).
168 */ 174 */
169 private void dispatchNextDecodeImageRequest() { 175 private void dispatchNextDecodeImageRequest() {
170 if (mRequests.entrySet().iterator().hasNext()) { 176 if (mRequests.entrySet().iterator().hasNext()) {
171 DecoderServiceParams params = mRequests.entrySet().iterator().next() .getValue(); 177 DecoderServiceParams params = mRequests.entrySet().iterator().next() .getValue();
178 params.mTimestamp = SystemClock.elapsedRealtime();
172 dispatchDecodeImageRequest(params.mFilePath, params.mSize); 179 dispatchDecodeImageRequest(params.mFilePath, params.mSize);
173 } 180 }
174 } 181 }
175 182
176 /** 183 /**
177 * Ties up all the loose ends from the decoding request (communicates the re sults of the 184 * Ties up all the loose ends from the decoding request (communicates the re sults of the
178 * decoding process back to the client, and takes care of house-keeping chor es regarding 185 * decoding process back to the client, and takes care of house-keeping chor es regarding
179 * the request queue). 186 * the request queue).
180 * @param filePath The path to the image that was just decoded. 187 * @param filePath The path to the image that was just decoded.
181 * @param bitmap The resulting decoded bitmap. 188 * @param bitmap The resulting decoded bitmap.
189 * @param decodeTime The length of time it took to decode the bitmap.
182 */ 190 */
183 public void closeRequest(String filePath, Bitmap bitmap) { 191 public void closeRequest(String filePath, Bitmap bitmap, long decodeTime) {
184 DecoderServiceParams params = getRequests().get(filePath); 192 DecoderServiceParams params = getRequests().get(filePath);
185 if (params != null) { 193 if (params != null) {
194 long endRpcCall = SystemClock.elapsedRealtime();
195 RecordHistogram.recordTimesHistogram("Android.PhotoPicker.RequestPro cessTime",
196 endRpcCall - params.mTimestamp, TimeUnit.MILLISECONDS);
197
186 params.mCallback.imageDecodedCallback(filePath, bitmap); 198 params.mCallback.imageDecodedCallback(filePath, bitmap);
199
200 if (decodeTime != -1) {
201 RecordHistogram.recordTimesHistogram(
202 "Android.PhotoPicker.ImageDecodeTime", decodeTime, TimeU nit.MILLISECONDS);
203 }
Theresa 2017/05/31 18:40:02 It would also be interesting to record the size of
Finnur 2017/06/01 15:13:55 I've added metrics for CacheHits for the high-res
187 getRequests().remove(filePath); 204 getRequests().remove(filePath);
188 } 205 }
189 dispatchNextDecodeImageRequest(); 206 dispatchNextDecodeImageRequest();
190 } 207 }
191 208
192 /** 209 /**
193 * Communicates with the server to decode a single bitmap. 210 * Communicates with the server to decode a single bitmap.
194 * @param filePath The path to the image on disk. 211 * @param filePath The path to the image on disk.
195 * @param size The requested width and height of the resulting bitmap. 212 * @param size The requested width and height of the resulting bitmap.
196 */ 213 */
197 private void dispatchDecodeImageRequest(String filePath, int size) { 214 private void dispatchDecodeImageRequest(String filePath, int size) {
198 // Obtain a file descriptor to send over to the sandboxed process. 215 // Obtain a file descriptor to send over to the sandboxed process.
199 File file = new File(filePath); 216 File file = new File(filePath);
200 FileInputStream inputFile = null; 217 FileInputStream inputFile = null;
201 ParcelFileDescriptor pfd = null; 218 ParcelFileDescriptor pfd = null;
202 Bundle bundle = new Bundle(); 219 Bundle bundle = new Bundle();
203 220
204 // The restricted utility process can't open the file to read the 221 // The restricted utility process can't open the file to read the
205 // contents, so we need to obtain a file descriptor to pass over. 222 // contents, so we need to obtain a file descriptor to pass over.
206 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 223 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
207 try { 224 try {
208 try { 225 try {
209 inputFile = new FileInputStream(file); 226 inputFile = new FileInputStream(file);
210 FileDescriptor fd = inputFile.getFD(); 227 FileDescriptor fd = inputFile.getFD();
211 pfd = ParcelFileDescriptor.dup(fd); 228 pfd = ParcelFileDescriptor.dup(fd);
212 bundle.putParcelable(DecoderService.KEY_FILE_DESCRIPTOR, pfd); 229 bundle.putParcelable(DecoderService.KEY_FILE_DESCRIPTOR, pfd);
213 } catch (IOException e) { 230 } catch (IOException e) {
214 Log.e(TAG, "Unable to obtain FileDescriptor: " + e); 231 Log.e(TAG, "Unable to obtain FileDescriptor: " + e);
215 closeRequest(filePath, null); 232 closeRequest(filePath, null, -1);
216 } 233 }
217 } finally { 234 } finally {
218 try { 235 try {
219 if (inputFile != null) inputFile.close(); 236 if (inputFile != null) inputFile.close();
220 } catch (IOException e) { 237 } catch (IOException e) {
221 Log.e(TAG, "Unable to close inputFile: " + e); 238 Log.e(TAG, "Unable to close inputFile: " + e);
222 } 239 }
223 StrictMode.setThreadPolicy(oldPolicy); 240 StrictMode.setThreadPolicy(oldPolicy);
224 } 241 }
225 242
226 if (pfd == null) return; 243 if (pfd == null) return;
227 244
228 // Prepare and send the data over. 245 // Prepare and send the data over.
229 Message payload = Message.obtain(null, DecoderService.MSG_DECODE_IMAGE); 246 Message payload = Message.obtain(null, DecoderService.MSG_DECODE_IMAGE);
230 payload.replyTo = mMessenger; 247 payload.replyTo = mMessenger;
231 bundle.putString(DecoderService.KEY_FILE_PATH, filePath); 248 bundle.putString(DecoderService.KEY_FILE_PATH, filePath);
232 bundle.putInt(DecoderService.KEY_SIZE, size); 249 bundle.putInt(DecoderService.KEY_SIZE, size);
233 payload.setData(bundle); 250 payload.setData(bundle);
234 try { 251 try {
235 mService.send(payload); 252 mService.send(payload);
236 pfd.close(); 253 pfd.close();
237 } catch (RemoteException e) { 254 } catch (RemoteException e) {
238 Log.e(TAG, "Communications failed (Remote): " + e); 255 Log.e(TAG, "Communications failed (Remote): " + e);
239 closeRequest(filePath, null); 256 closeRequest(filePath, null, -1);
240 } catch (IOException e) { 257 } catch (IOException e) {
241 Log.e(TAG, "Communications failed (IO): " + e); 258 Log.e(TAG, "Communications failed (IO): " + e);
242 closeRequest(filePath, null); 259 closeRequest(filePath, null, -1);
243 } 260 }
244 } 261 }
245 262
246 /** 263 /**
247 * Cancels a request to decode an image (if it hasn't already been dispatche d). 264 * Cancels a request to decode an image (if it hasn't already been dispatche d).
248 * @param filePath The path to the image to cancel decoding. 265 * @param filePath The path to the image to cancel decoding.
249 */ 266 */
250 public void cancelDecodeImage(String filePath) { 267 public void cancelDecodeImage(String filePath) {
251 mRequests.remove(filePath); 268 mRequests.remove(filePath);
252 } 269 }
(...skipping 24 matching lines...) Expand all
277 switch (msg.what) { 294 switch (msg.what) {
278 case DecoderService.MSG_IMAGE_DECODED_REPLY: 295 case DecoderService.MSG_IMAGE_DECODED_REPLY:
279 Bundle payload = msg.getData(); 296 Bundle payload = msg.getData();
280 297
281 // Read the reply back from the service. 298 // Read the reply back from the service.
282 String filePath = payload.getString(DecoderService.KEY_FILE_ PATH); 299 String filePath = payload.getString(DecoderService.KEY_FILE_ PATH);
283 Boolean success = payload.getBoolean(DecoderService.KEY_SUCC ESS); 300 Boolean success = payload.getBoolean(DecoderService.KEY_SUCC ESS);
284 Bitmap bitmap = success 301 Bitmap bitmap = success
285 ? (Bitmap) payload.getParcelable(DecoderService.KEY_ IMAGE_BITMAP) 302 ? (Bitmap) payload.getParcelable(DecoderService.KEY_ IMAGE_BITMAP)
286 : null; 303 : null;
287 host.closeRequest(filePath, bitmap); 304 long decodeTime = payload.getLong(DecoderService.KEY_DECODE_ TIME);
305 host.closeRequest(filePath, bitmap, decodeTime);
288 break; 306 break;
289 default: 307 default:
290 super.handleMessage(msg); 308 super.handleMessage(msg);
291 } 309 }
292 } 310 }
293 } 311 }
294 } 312 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698