summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2013-04-05 20:57:01 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-04-05 20:57:01 +0000
commit4a706bc6f1dcf4483b282d5758e22482cf02506f (patch)
treeb30d59c9474bc4499b3c433dbd5135891567c27a
parent5feceebb892d4cb5777cea3c6174b206705d456b (diff)
parent1951ce86c21445ac191e4d2d95233f4f5c096b56 (diff)
downloadframeworks_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.java10
-rw-r--r--core/java/android/view/InputChannel.java12
-rw-r--r--core/java/com/android/internal/view/InputBindResult.java2
-rw-r--r--core/jni/android_view_InputChannel.cpp11
-rw-r--r--include/androidfw/InputTransport.h3
-rw-r--r--libs/androidfw/InputTransport.cpp5
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java25
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);