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:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ---
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user