Index: chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java |
index 9f307683bb5558327b1ad5405d2d2108b72c895b..77c06c198c45fdb7d417b3f2d6171dd4ab1889a7 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java |
@@ -8,10 +8,7 @@ import android.app.Service; |
import android.content.Intent; |
import android.graphics.Bitmap; |
import android.os.Bundle; |
-import android.os.Handler; |
import android.os.IBinder; |
-import android.os.Message; |
-import android.os.Messenger; |
import android.os.ParcelFileDescriptor; |
import android.os.RemoteException; |
import android.os.SystemClock; |
@@ -25,19 +22,10 @@ import java.io.IOException; |
* A service to accept requests to take image file contents and decode them. |
*/ |
public class DecoderService extends Service { |
- // Message ids for communicating with the client. |
- |
- // A message sent by the client to decode an image. |
- static final int MSG_DECODE_IMAGE = 1; |
- // A message sent by the server to notify the client of the results of the decoding. |
- static final int MSG_IMAGE_DECODED_REPLY = 2; |
- |
// The keys for the bundle when passing data to and from this service. |
static final String KEY_FILE_DESCRIPTOR = "file_descriptor"; |
static final String KEY_FILE_PATH = "file_path"; |
static final String KEY_IMAGE_BITMAP = "image_bitmap"; |
- static final String KEY_IMAGE_BYTE_COUNT = "image_byte_count"; |
- static final String KEY_IMAGE_DESCRIPTOR = "image_descriptor"; |
static final String KEY_SIZE = "size"; |
static final String KEY_SUCCESS = "success"; |
static final String KEY_DECODE_TIME = "decode_time"; |
@@ -45,98 +33,78 @@ public class DecoderService extends Service { |
// A tag for logging error messages. |
private static final String TAG = "ImageDecoder"; |
- /** |
- * Handler for incoming messages from clients. |
- */ |
- static class IncomingHandler extends Handler { |
- @Override |
- public void handleMessage(Message msg) { |
- switch (msg.what) { |
- case MSG_DECODE_IMAGE: |
- Bundle bundle = null; |
- Messenger client = null; |
- String filePath = ""; |
- int size = 0; |
- try { |
- Bundle payload = msg.getData(); |
- client = msg.replyTo; |
- |
- filePath = payload.getString(KEY_FILE_PATH); |
- ParcelFileDescriptor pfd = payload.getParcelable(KEY_FILE_DESCRIPTOR); |
- size = payload.getInt(KEY_SIZE); |
- |
- // Setup a minimum viable response to parent process. Will be fleshed out |
- // further below. |
- bundle = new Bundle(); |
- bundle.putString(KEY_FILE_PATH, filePath); |
- bundle.putBoolean(KEY_SUCCESS, false); |
- |
- FileDescriptor fd = pfd.getFileDescriptor(); |
- |
- long begin = SystemClock.elapsedRealtime(); |
- Bitmap bitmap = BitmapUtils.decodeBitmapFromFileDescriptor(fd, size); |
- long decodeTime = SystemClock.elapsedRealtime() - begin; |
- |
- try { |
- pfd.close(); |
- } catch (IOException e) { |
- Log.e(TAG, "Closing failed " + filePath + " (size: " + size + ") " + e); |
- } |
- |
- if (bitmap == null) { |
- Log.e(TAG, "Decode failed " + filePath + " (size: " + size + ")"); |
- sendReply(client, bundle); // Sends SUCCESS == false; |
- return; |
- } |
- |
- // The most widely supported, easiest, and reasonably efficient method is to |
- // decode to an immutable bitmap and just return the bitmap over binder. It |
- // will internally memcpy itself to ashmem and then just send over the file |
- // descriptor. In the receiving process it will just leave the bitmap on |
- // ashmem since it's immutable and carry on. |
- bundle.putParcelable(KEY_IMAGE_BITMAP, bitmap); |
- bundle.putBoolean(KEY_SUCCESS, true); |
- bundle.putLong(KEY_DECODE_TIME, decodeTime); |
- sendReply(client, bundle); |
- bitmap.recycle(); |
- } catch (Exception e) { |
- // This service has no UI and maintains no state so if it crashes on |
- // decoding a photo, it is better UX to eat the exception instead of showing |
- // a crash dialog and discarding other requests that have already been sent. |
- Log.e(TAG, |
- "Unexpected error during decoding " + filePath + " (size: " + size |
- + ") " + e); |
- |
- if (bundle != null && client != null) sendReply(client, bundle); |
- } |
- break; |
- default: |
- super.handleMessage(msg); |
+ @Override |
+ public void onCreate() { |
+ super.onCreate(); |
+ } |
+ |
+ @Override |
+ public IBinder onBind(Intent intent) { |
+ return mBinder; |
+ } |
+ |
+ private final IDecoderService.Stub mBinder = new IDecoderService.Stub() { |
+ public void decodeImage(Bundle payload, IDecoderServiceCallback callback) { |
+ Bundle bundle = null; |
+ String filePath = ""; |
+ int size = 0; |
+ try { |
+ filePath = payload.getString(KEY_FILE_PATH); |
+ ParcelFileDescriptor pfd = payload.getParcelable(KEY_FILE_DESCRIPTOR); |
+ size = payload.getInt(KEY_SIZE); |
+ |
+ // Setup a minimum viable response to parent process. Will be fleshed out |
+ // further below. |
+ bundle = new Bundle(); |
+ bundle.putString(KEY_FILE_PATH, filePath); |
+ bundle.putBoolean(KEY_SUCCESS, false); |
+ |
+ FileDescriptor fd = pfd.getFileDescriptor(); |
+ |
+ long begin = SystemClock.elapsedRealtime(); |
+ Bitmap bitmap = BitmapUtils.decodeBitmapFromFileDescriptor(fd, size); |
+ long decodeTime = SystemClock.elapsedRealtime() - begin; |
+ |
+ try { |
+ pfd.close(); |
+ } catch (IOException e) { |
+ Log.e(TAG, "Closing failed " + filePath + " (size: " + size + ") " + e); |
+ } |
+ |
+ if (bitmap == null) { |
+ Log.e(TAG, "Decode failed " + filePath + " (size: " + size + ")"); |
+ sendReply(callback, bundle); // Sends SUCCESS == false; |
+ return; |
+ } |
+ |
+ // The most widely supported, easiest, and reasonably efficient method is to |
+ // decode to an immutable bitmap and just return the bitmap over binder. It |
+ // will internally memcpy itself to ashmem and then just send over the file |
+ // descriptor. In the receiving process it will just leave the bitmap on |
+ // ashmem since it's immutable and carry on. |
+ bundle.putParcelable(KEY_IMAGE_BITMAP, bitmap); |
+ bundle.putBoolean(KEY_SUCCESS, true); |
+ bundle.putLong(KEY_DECODE_TIME, decodeTime); |
+ sendReply(callback, bundle); |
+ bitmap.recycle(); |
+ } catch (Exception e) { |
+ // This service has no UI and maintains no state so if it crashes on |
+ // decoding a photo, it is better UX to eat the exception instead of showing |
+ // a crash dialog and discarding other requests that have already been sent. |
+ Log.e(TAG, |
+ "Unexpected error during decoding " + filePath + " (size: " + size + ") " |
+ + e); |
+ |
+ if (bundle != null) sendReply(callback, bundle); |
} |
} |
- private void sendReply(Messenger client, Bundle bundle) { |
- Message reply = Message.obtain(null, MSG_IMAGE_DECODED_REPLY); |
- reply.setData(bundle); |
+ private void sendReply(IDecoderServiceCallback callback, Bundle bundle) { |
try { |
- client.send(reply); |
+ callback.onDecodeImageDone(bundle); |
} catch (RemoteException remoteException) { |
Log.e(TAG, "Remote error while replying: " + remoteException); |
} |
} |
- } |
- |
- /** |
- * The target we publish for clients to send messages to IncomingHandler. |
- */ |
- final Messenger mMessenger = new Messenger(new IncomingHandler()); |
- |
- /** |
- * When binding to the service, we return an interface to our messenger |
- * for sending messages to the service. |
- */ |
- @Override |
- public IBinder onBind(Intent intent) { |
- return mMessenger.getBinder(); |
- } |
+ }; |
} |