Index: chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java |
index e5cf11c0f56eff54e0fa97d7b8a32f18e8bf22ff..8122b50e6dc91593f48b506e504b96334561ca32 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java |
@@ -10,16 +10,14 @@ import android.content.Intent; |
import android.content.ServiceConnection; |
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.StrictMode; |
import android.os.SystemClock; |
import org.chromium.base.Log; |
+import org.chromium.base.ThreadUtils; |
import org.chromium.base.metrics.RecordHistogram; |
import org.chromium.chrome.browser.util.ConversionUtils; |
@@ -27,17 +25,31 @@ import java.io.File; |
import java.io.FileDescriptor; |
import java.io.FileInputStream; |
import java.io.IOException; |
-import java.lang.ref.WeakReference; |
import java.util.LinkedHashMap; |
import java.util.concurrent.TimeUnit; |
/** |
* A class to communicate with the {@link DecoderService}. |
*/ |
-public class DecoderServiceHost { |
+public class DecoderServiceHost extends IDecoderServiceCallback.Stub { |
// A tag for logging error messages. |
private static final String TAG = "ImageDecoderHost"; |
+ IDecoderService mIRemoteService; |
+ private ServiceConnection mConnection = new ServiceConnection() { |
+ public void onServiceConnected(ComponentName className, IBinder service) { |
+ mIRemoteService = IDecoderService.Stub.asInterface(service); |
+ mBound = true; |
+ mCallback.serviceReady(); |
+ } |
+ |
+ public void onServiceDisconnected(ComponentName className) { |
+ Log.e(TAG, "Service has unexpectedly disconnected"); |
+ mIRemoteService = null; |
+ mBound = false; |
+ } |
+ }; |
+ |
/** |
* Interface for notifying clients of the service being ready. |
*/ |
@@ -60,30 +72,6 @@ public class DecoderServiceHost { |
void imageDecodedCallback(String filePath, Bitmap bitmap); |
} |
- /** |
- * Class for interacting with the main interface of the service. |
- */ |
- private class DecoderServiceConnection implements ServiceConnection { |
- // The callback to use to notify the service being ready. |
- private ServiceReadyCallback mCallback; |
- |
- public DecoderServiceConnection(ServiceReadyCallback callback) { |
- mCallback = callback; |
- } |
- |
- // Called when a connection to the service has been established. |
- public void onServiceConnected(ComponentName name, IBinder service) { |
- mService = new Messenger(service); |
- mBound = true; |
- mCallback.serviceReady(); |
- } |
- |
- // Called when a connection to the service has been lost. |
- public void onServiceDisconnected(ComponentName name) { |
- mBound = false; |
- } |
- } |
- |
/** |
* Class for keeping track of the data involved with each request. |
*/ |
@@ -116,24 +104,18 @@ public class DecoderServiceHost { |
// The callback used to notify the client when the service is ready. |
private ServiceReadyCallback mCallback; |
- // Messenger for communicating with the remote service. |
- Messenger mService = null; |
- |
- // Our service connection to the {@link DecoderService}. |
- private DecoderServiceConnection mConnection; |
- |
// Flag indicating whether we are bound to the service. |
- boolean mBound; |
+ private boolean mBound; |
- // The inbound messenger used by the remote service to communicate with us. |
- final Messenger mMessenger = new Messenger(new IncomingHandler(this)); |
+ private final Context mContext; |
/** |
* The DecoderServiceHost constructor. |
* @param callback The callback to use when communicating back to the client. |
*/ |
- public DecoderServiceHost(ServiceReadyCallback callback) { |
+ public DecoderServiceHost(ServiceReadyCallback callback, Context context) { |
mCallback = callback; |
+ mContext = context; |
} |
/** |
@@ -141,9 +123,9 @@ public class DecoderServiceHost { |
* @param context The context to use. |
*/ |
public void bind(Context context) { |
- mConnection = new DecoderServiceConnection(mCallback); |
- Intent intent = new Intent(context, DecoderService.class); |
- context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); |
+ Intent intent = new Intent(mContext, DecoderService.class); |
+ intent.setAction(IDecoderService.class.getName()); |
+ mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); |
} |
/** |
@@ -181,6 +163,26 @@ public class DecoderServiceHost { |
} |
} |
+ @Override |
+ public void onDecodeImageDone(final Bundle payload) { |
+ // As per the Android documentation, AIDL callbacks can (and will) happen on any thread, so |
+ // make sure the code runs on the UI thread, since further down the callchain the code will |
+ // end up creating UI objects. |
+ ThreadUtils.runOnUiThread(new Runnable() { |
+ @Override |
+ public void run() { |
+ // Read the reply back from the service. |
+ String filePath = payload.getString(DecoderService.KEY_FILE_PATH); |
+ Boolean success = payload.getBoolean(DecoderService.KEY_SUCCESS); |
+ Bitmap bitmap = success |
+ ? (Bitmap) payload.getParcelable(DecoderService.KEY_IMAGE_BITMAP) |
+ : null; |
+ long decodeTime = payload.getLong(DecoderService.KEY_DECODE_TIME); |
+ closeRequest(filePath, bitmap, decodeTime); |
+ } |
+ }); |
+ } |
+ |
/** |
* Ties up all the loose ends from the decoding request (communicates the results of the |
* decoding process back to the client, and takes care of house-keeping chores regarding |
@@ -248,13 +250,10 @@ public class DecoderServiceHost { |
if (pfd == null) return; |
// Prepare and send the data over. |
- Message payload = Message.obtain(null, DecoderService.MSG_DECODE_IMAGE); |
- payload.replyTo = mMessenger; |
bundle.putString(DecoderService.KEY_FILE_PATH, filePath); |
bundle.putInt(DecoderService.KEY_SIZE, size); |
- payload.setData(bundle); |
try { |
- mService.send(payload); |
+ mIRemoteService.decodeImage(bundle, this); |
pfd.close(); |
} catch (RemoteException e) { |
Log.e(TAG, "Communications failed (Remote): " + e); |
@@ -272,46 +271,4 @@ public class DecoderServiceHost { |
public void cancelDecodeImage(String filePath) { |
mRequests.remove(filePath); |
} |
- |
- /** |
- * A class for handling communications from the service to us. |
- */ |
- static class IncomingHandler extends Handler { |
- // The DecoderServiceHost object to communicate with. |
- private final WeakReference<DecoderServiceHost> mHost; |
- |
- /** |
- * Constructor for IncomingHandler. |
- * @param host The DecoderServiceHost object to communicate with. |
- */ |
- IncomingHandler(DecoderServiceHost host) { |
- mHost = new WeakReference<DecoderServiceHost>(host); |
- } |
- |
- @Override |
- public void handleMessage(Message msg) { |
- DecoderServiceHost host = mHost.get(); |
- if (host == null) { |
- super.handleMessage(msg); |
- return; |
- } |
- |
- switch (msg.what) { |
- case DecoderService.MSG_IMAGE_DECODED_REPLY: |
- Bundle payload = msg.getData(); |
- |
- // Read the reply back from the service. |
- String filePath = payload.getString(DecoderService.KEY_FILE_PATH); |
- Boolean success = payload.getBoolean(DecoderService.KEY_SUCCESS); |
- Bitmap bitmap = success |
- ? (Bitmap) payload.getParcelable(DecoderService.KEY_IMAGE_BITMAP) |
- : null; |
- long decodeTime = payload.getLong(DecoderService.KEY_DECODE_TIME); |
- host.closeRequest(filePath, bitmap, decodeTime); |
- break; |
- default: |
- super.handleMessage(msg); |
- } |
- } |
- } |
} |