diff options
author | Jeff Brown <jeffbrown@google.com> | 2013-04-05 20:57:01 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-04-05 20:57:01 +0000 |
commit | 4a706bc6f1dcf4483b282d5758e22482cf02506f (patch) | |
tree | b30d59c9474bc4499b3c433dbd5135891567c27a | |
parent | 5feceebb892d4cb5777cea3c6174b206705d456b (diff) | |
parent | 1951ce86c21445ac191e4d2d95233f4f5c096b56 (diff) | |
download | frameworks_base-4a706bc6f1dcf4483b282d5758e22482cf02506f.zip frameworks_base-4a706bc6f1dcf4483b282d5758e22482cf02506f.tar.gz frameworks_base-4a706bc6f1dcf4483b282d5758e22482cf02506f.tar.bz2 |
Merge "Correctly manage the lifecycle of IME InputChannels." into jb-mr2-dev
-rw-r--r-- | core/java/android/os/Binder.java | 10 | ||||
-rw-r--r-- | core/java/android/view/InputChannel.java | 12 | ||||
-rw-r--r-- | core/java/com/android/internal/view/InputBindResult.java | 2 | ||||
-rw-r--r-- | core/jni/android_view_InputChannel.cpp | 11 | ||||
-rw-r--r-- | include/androidfw/InputTransport.h | 3 | ||||
-rw-r--r-- | libs/androidfw/InputTransport.cpp | 5 | ||||
-rw-r--r-- | services/java/com/android/server/InputMethodManagerService.java | 25 |
7 files changed, 58 insertions, 10 deletions
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 16b4835..e9e7551 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -152,7 +152,15 @@ public class Binder implements IBinder { * not return until the current process is exiting. */ public static final native void joinThreadPool(); - + + /** + * Returns true if the specified interface is a proxy. + * @hide + */ + public static final boolean isProxy(IInterface iface) { + return iface.asBinder() != iface; + } + /** * Default constructor initializes the object. */ diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java index a797176..40ee1ad 100644 --- a/core/java/android/view/InputChannel.java +++ b/core/java/android/view/InputChannel.java @@ -54,6 +54,7 @@ public final class InputChannel implements Parcelable { private native void nativeTransferTo(InputChannel other); private native void nativeReadFromParcel(Parcel parcel); private native void nativeWriteToParcel(Parcel parcel); + private native void nativeDup(InputChannel target); private native String nativeGetName(); @@ -64,7 +65,7 @@ public final class InputChannel implements Parcelable { */ public InputChannel() { } - + @Override protected void finalize() throws Throwable { try { @@ -125,6 +126,15 @@ public final class InputChannel implements Parcelable { nativeTransferTo(outParameter); } + /** + * Duplicates the input channel. + */ + public InputChannel dup() { + InputChannel target = new InputChannel(); + nativeDup(target); + return target; + } + @Override public int describeContents() { return Parcelable.CONTENTS_FILE_DESCRIPTOR; diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java index 9143c61..14afe21 100644 --- a/core/java/com/android/internal/view/InputBindResult.java +++ b/core/java/com/android/internal/view/InputBindResult.java @@ -84,7 +84,7 @@ public final class InputBindResult implements Parcelable { dest.writeStrongInterface(method); if (channel != null) { dest.writeInt(1); - channel.writeToParcel(dest, 0); + channel.writeToParcel(dest, flags); } else { dest.writeInt(0); } diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp index 9c44a59..9fa9fe4 100644 --- a/core/jni/android_view_InputChannel.cpp +++ b/core/jni/android_view_InputChannel.cpp @@ -246,6 +246,15 @@ static jstring android_view_InputChannel_nativeGetName(JNIEnv* env, jobject obj) return name; } +static void android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jobject otherObj) { + NativeInputChannel* nativeInputChannel = + android_view_InputChannel_getNativeInputChannel(env, obj); + if (nativeInputChannel) { + android_view_InputChannel_setNativeInputChannel(env, otherObj, + new NativeInputChannel(nativeInputChannel->getInputChannel()->dup())); + } +} + // ---------------------------------------------------------------------------- static JNINativeMethod gInputChannelMethods[] = { @@ -262,6 +271,8 @@ static JNINativeMethod gInputChannelMethods[] = { (void*)android_view_InputChannel_nativeWriteToParcel }, { "nativeGetName", "()Ljava/lang/String;", (void*)android_view_InputChannel_nativeGetName }, + { "nativeDup", "(Landroid/view/InputChannel;)V", + (void*)android_view_InputChannel_nativeDup }, }; #define FIND_CLASS(var, className) \ diff --git a/include/androidfw/InputTransport.h b/include/androidfw/InputTransport.h index 5706bce..8712995 100644 --- a/include/androidfw/InputTransport.h +++ b/include/androidfw/InputTransport.h @@ -168,6 +168,9 @@ public: */ status_t receiveMessage(InputMessage* msg); + /* Returns a new object that has a duplicate of this channel's fd. */ + sp<InputChannel> dup() const; + private: String8 mName; int mFd; diff --git a/libs/androidfw/InputTransport.cpp b/libs/androidfw/InputTransport.cpp index 351c666..498389e 100644 --- a/libs/androidfw/InputTransport.cpp +++ b/libs/androidfw/InputTransport.cpp @@ -219,6 +219,11 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { return OK; } +sp<InputChannel> InputChannel::dup() const { + int fd = ::dup(getFd()); + return fd >= 0 ? new InputChannel(getName(), fd) : NULL; +} + // --- InputPublisher --- diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 3b541ec..a28c387 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1070,7 +1070,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Attach new input asks to show input"); showCurrentInputLocked(getAppShowFlags(), null); } - return new InputBindResult(session.session, session.channel, mCurId, mCurSeq); + return new InputBindResult(session.session, + session.channel != null ? session.channel.dup() : null, mCurId, mCurSeq); } InputBindResult startInputLocked(IInputMethodClient client, @@ -2357,13 +2358,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return true; case MSG_CREATE_SESSION: { args = (SomeArgs)msg.obj; + IInputMethod method = (IInputMethod)args.arg1; InputChannel channel = (InputChannel)args.arg2; try { - ((IInputMethod)args.arg1).createSession(channel, - (IInputSessionCallback)args.arg3); + method.createSession(channel, (IInputSessionCallback)args.arg3); } catch (RemoteException e) { } finally { - if (channel != null) { + // Dispose the channel if the input method is not local to this process + // because the remote proxy will get its own copy when unparceled. + if (channel != null && Binder.isProxy(method)) { channel.dispose(); } } @@ -2404,16 +2407,24 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // There is nothing interesting about the last client dying. } return true; - case MSG_BIND_METHOD: + case MSG_BIND_METHOD: { args = (SomeArgs)msg.obj; + IInputMethodClient client = (IInputMethodClient)args.arg1; + InputBindResult res = (InputBindResult)args.arg2; try { - ((IInputMethodClient)args.arg1).onBindMethod( - (InputBindResult)args.arg2); + client.onBindMethod(res); } catch (RemoteException e) { Slog.w(TAG, "Client died receiving input method " + args.arg2); + } finally { + // Dispose the channel if the input method is not local to this process + // because the remote proxy will get its own copy when unparceled. + if (res.channel != null && Binder.isProxy(client)) { + res.channel.dispose(); + } } args.recycle(); return true; + } case MSG_SET_ACTIVE: try { ((ClientState)msg.obj).client.setActive(msg.arg1 != 0); |