am 4a706bc6: Merge "Correctly manage the lifecycle of IME InputChannels." into jb-mr2-dev

* commit '4a706bc6f1dcf4483b282d5758e22482cf02506f':
  Correctly manage the lifecycle of IME InputChannels.
This commit is contained in:
Jeff Brown
2013-04-05 14:03:06 -07:00
committed by Android Git Automerger
7 changed files with 58 additions and 10 deletions

View File

@@ -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.
*/

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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) \

View File

@@ -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;

View File

@@ -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 ---

View File

@@ -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);