am 3a2854bc: Merge "Queues, queues, queues and input." into jb-mr2-dev

* commit '3a2854bcee08e3af3ca1b042c1fef6ca68f8c70a':
  Queues, queues, queues and input.
This commit is contained in:
Jeff Brown
2013-04-08 17:03:20 -07:00
committed by Android Git Automerger
14 changed files with 1055 additions and 953 deletions

View File

@ -371,9 +371,9 @@ class ContextImpl extends Context {
return new DisplayManager(ctx.getOuterContext());
}});
registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return InputMethodManager.getInstance(ctx);
registerService(INPUT_METHOD_SERVICE, new StaticServiceFetcher() {
public Object createStaticService() {
return InputMethodManager.getInstance();
}});
registerService(TEXT_SERVICES_MANAGER_SERVICE, new ServiceFetcher() {

View File

@ -1,7 +1,20 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app;
import com.android.internal.view.IInputMethodSession;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@ -25,7 +38,6 @@ import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.inputmethod.InputMethodManager;
import java.io.File;
import java.lang.ref.WeakReference;
/**
* Convenience for implementing an activity that will be implemented
@ -65,7 +77,6 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
private NativeContentView mNativeContentView;
private InputMethodManager mIMM;
private InputMethodCallback mInputMethodCallback;
private int mNativeHandle;
@ -117,22 +128,6 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
super(context, attrs);
}
}
static final class InputMethodCallback implements InputMethodManager.FinishedEventCallback {
WeakReference<NativeActivity> mNa;
InputMethodCallback(NativeActivity na) {
mNa = new WeakReference<NativeActivity>(na);
}
@Override
public void finishedEvent(int seq, boolean handled) {
NativeActivity na = mNa.get();
if (na != null) {
na.finishPreDispatchKeyEventNative(na.mNativeHandle, seq, handled);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -141,7 +136,6 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
ActivityInfo ai;
mIMM = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
mInputMethodCallback = new InputMethodCallback(this);
getWindow().takeSurface(this);
getWindow().takeInputQueue(this);
@ -353,7 +347,8 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
}
void preDispatchKeyEvent(KeyEvent event, int seq) {
mIMM.dispatchInputEvent(this, seq, event, mInputMethodCallback);
// FIXME: Input dispatch should be redirected back through ViewRootImpl again.
finishPreDispatchKeyEventNative(mNativeHandle, seq, false);
}
void setWindowFlags(int flags, int mask) {

View File

@ -709,7 +709,7 @@ public class WallpaperManager {
public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
try {
//Log.v(TAG, "Sending new wallpaper offsets from app...");
WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
WindowManagerGlobal.getWindowSession().setWallpaperPosition(
windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
@ -747,7 +747,7 @@ public class WallpaperManager {
int x, int y, int z, Bundle extras) {
try {
//Log.v(TAG, "Sending new wallpaper offsets from app...");
WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
WindowManagerGlobal.getWindowSession().sendWallpaperCommand(
windowToken, action, x, y, z, extras, false);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
@ -767,7 +767,7 @@ public class WallpaperManager {
*/
public void clearWallpaperOffsets(IBinder windowToken) {
try {
WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
WindowManagerGlobal.getWindowSession().setWallpaperPosition(
windowToken, -1, -1, -1, -1);
} catch (RemoteException e) {
// Ignore.

View File

@ -256,6 +256,12 @@ public abstract class Context {
* Return the Looper for the main thread of the current process. This is
* the thread used to dispatch calls to application components (activities,
* services, etc).
* <p>
* By definition, this method returns the same result as would be obtained
* by calling {@link Looper#getMainLooper() Looper.getMainLooper()}.
* </p>
*
* @return The main looper.
*/
public abstract Looper getMainLooper();

View File

@ -1,94 +0,0 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os;
import android.util.Log;
import java.util.HashMap;
/**
* A class to help with measuring latency in your code.
*
* Suggested usage:
* 1) Instanciate a LatencyTimer as a class field.
* private [static] LatencyTimer mLt = new LatencyTimer(100, 1000);
* 2) At various points in the code call sample with a string and the time delta to some fixed time.
* The string should be unique at each point of the code you are measuring.
* mLt.sample("before processing event", System.nanoTime() - event.getEventTimeNano());
* processEvent(event);
* mLt.sample("after processing event ", System.nanoTime() - event.getEventTimeNano());
*
* @hide
*/
public final class LatencyTimer
{
final String TAG = "LatencyTimer";
final int mSampleSize;
final int mScaleFactor;
volatile HashMap<String, long[]> store = new HashMap<String, long[]>();
/**
* Creates a LatencyTimer object
* @param sampleSize number of samples to collect before printing out the average
* @param scaleFactor divisor used to make each sample smaller to prevent overflow when
* (sampleSize * average sample value)/scaleFactor > Long.MAX_VALUE
*/
public LatencyTimer(int sampleSize, int scaleFactor) {
if (scaleFactor == 0) {
scaleFactor = 1;
}
mScaleFactor = scaleFactor;
mSampleSize = sampleSize;
}
/**
* Add a sample delay for averaging.
* @param tag string used for printing out the result. This should be unique at each point of
* this called.
* @param delta time difference from an unique point of reference for a particular iteration
*/
public void sample(String tag, long delta) {
long[] array = getArray(tag);
// array[mSampleSize] holds the number of used entries
final int index = (int) array[mSampleSize]++;
array[index] = delta;
if (array[mSampleSize] == mSampleSize) {
long totalDelta = 0;
for (long d : array) {
totalDelta += d/mScaleFactor;
}
array[mSampleSize] = 0;
Log.i(TAG, tag + " average = " + totalDelta / mSampleSize);
}
}
private long[] getArray(String tag) {
long[] data = store.get(tag);
if (data == null) {
synchronized(store) {
data = store.get(tag);
if (data == null) {
data = new long[mSampleSize + 1];
store.put(tag, data);
data[mSampleSize] = 0;
}
}
}
return data;
}
}

View File

@ -191,6 +191,14 @@ public final class Looper {
mThread = Thread.currentThread();
}
/**
* Returns true if the current thread is this looper's thread.
* @hide
*/
public boolean isCurrentThread() {
return Thread.currentThread() == mThread;
}
/**
* Quits the looper.
*

View File

@ -762,7 +762,7 @@ public abstract class WallpaperService extends Service {
mWindowToken = wrapper.mWindowToken;
mSurfaceHolder.setSizeFromLayout();
mInitializing = true;
mSession = WindowManagerGlobal.getWindowSession(getMainLooper());
mSession = WindowManagerGlobal.getWindowSession();
mWindow.setSession(mSession);

File diff suppressed because it is too large Load Diff

View File

@ -136,11 +136,11 @@ public final class WindowManagerGlobal {
}
}
public static IWindowSession getWindowSession(Looper mainLooper) {
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
imm.getClient(), imm.getInputContext());
@ -351,7 +351,7 @@ public final class WindowManagerGlobal {
View view = root.getView();
if (view != null) {
InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
InputMethodManager imm = InputMethodManager.getInstance();
if (imm != null) {
imm.windowDismissed(mViews[index].getWindowToken());
}

View File

@ -34,9 +34,11 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.Trace;
import android.text.style.SuggestionSpan;
import android.util.Log;
import android.util.Pools.Pool;
import android.util.Pools.SimplePool;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.view.InputChannel;
@ -45,6 +47,7 @@ import android.view.InputEventSender;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewRootImpl;
import android.util.SparseArray;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@ -200,8 +203,9 @@ public final class InputMethodManager {
static final boolean DEBUG = false;
static final String TAG = "InputMethodManager";
static final Object mInstanceSync = new Object();
static InputMethodManager mInstance;
static final String PENDING_EVENT_COUNTER = "aq:imm";
static InputMethodManager sInstance;
/**
* @hide Flag for IInputMethodManager.windowGainedFocus: a view in
@ -232,7 +236,14 @@ public final class InputMethodManager {
*/
static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
private static final int MAX_PENDING_EVENT_POOL_SIZE = 4;
/** @hide */
public static final int DISPATCH_IN_PROGRESS = -1;
/** @hide */
public static final int DISPATCH_NOT_HANDLED = 0;
/** @hide */
public static final int DISPATCH_HANDLED = 1;
final IInputMethodManager mService;
final Looper mMainLooper;
@ -323,10 +334,8 @@ public final class InputMethodManager {
InputChannel mCurChannel;
ImeInputEventSender mCurSender;
PendingEvent mPendingEventPool;
int mPendingEventPoolSize;
PendingEvent mPendingEventHead;
PendingEvent mPendingEventTail;
final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
// -----------------------------------------------------------
@ -334,8 +343,10 @@ public final class InputMethodManager {
static final int MSG_BIND = 2;
static final int MSG_UNBIND = 3;
static final int MSG_SET_ACTIVE = 4;
static final int MSG_EVENT_TIMEOUT = 5;
static final int MSG_SEND_INPUT_EVENT = 5;
static final int MSG_TIMEOUT_INPUT_EVENT = 6;
static final int MSG_FLUSH_INPUT_EVENT = 7;
class H extends Handler {
H(Looper looper) {
super(looper, null, true);
@ -453,15 +464,16 @@ public final class InputMethodManager {
}
return;
}
case MSG_EVENT_TIMEOUT: {
// Even though the message contains both the sequence number
// and the PendingEvent object itself, we only pass the
// sequence number to the timeoutEvent function because it's
// possible for the PendingEvent object to be dequeued and
// recycled concurrently. To avoid a possible race, we make
// a point of always looking up the PendingEvent within the
// queue given only the sequence number of the event.
timeoutEvent(msg.arg1);
case MSG_SEND_INPUT_EVENT: {
sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
return;
}
case MSG_TIMEOUT_INPUT_EVENT: {
finishedInputEvent(msg.arg1, false, true);
return;
}
case MSG_FLUSH_INPUT_EVENT: {
finishedInputEvent(msg.arg1, false, false);
return;
}
}
@ -538,10 +550,6 @@ public final class InputMethodManager {
mH = new H(looper);
mIInputContext = new ControlledInputConnectionWrapper(looper,
mDummyInputConnection, this);
if (mInstance == null) {
mInstance = this;
}
}
/**
@ -549,25 +557,15 @@ public final class InputMethodManager {
* doesn't already exist.
* @hide
*/
static public InputMethodManager getInstance(Context context) {
return getInstance(context.getMainLooper());
}
/**
* Internally, the input method manager can't be context-dependent, so
* we have this here for the places that need it.
* @hide
*/
static public InputMethodManager getInstance(Looper mainLooper) {
synchronized (mInstanceSync) {
if (mInstance != null) {
return mInstance;
public static InputMethodManager getInstance() {
synchronized (InputMethodManager.class) {
if (sInstance == null) {
IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
sInstance = new InputMethodManager(service, Looper.getMainLooper());
}
IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
mInstance = new InputMethodManager(service, mainLooper);
return sInstance;
}
return mInstance;
}
/**
@ -575,8 +573,8 @@ public final class InputMethodManager {
* if it exists.
* @hide
*/
static public InputMethodManager peekInstance() {
return mInstance;
public static InputMethodManager peekInstance() {
return sInstance;
}
/** @hide */
@ -1585,13 +1583,18 @@ public final class InputMethodManager {
}
/**
* Dispatches an input event to the IME.
*
* Returns {@link #DISPATCH_HANDLED} if the event was handled.
* Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
* Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
* callback will be invoked later.
*
* @hide
*/
public int dispatchInputEvent(Context context, int seq, InputEvent event,
FinishedEventCallback callback) {
public int dispatchInputEvent(InputEvent event, Object token,
FinishedInputEventCallback callback, Handler handler) {
synchronized (mH) {
if (DEBUG) Log.d(TAG, "dispatchInputEvent");
if (mCurMethod != null) {
if (event instanceof KeyEvent) {
KeyEvent keyEvent = (KeyEvent)event;
@ -1599,144 +1602,140 @@ public final class InputMethodManager {
&& keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
&& keyEvent.getRepeatCount() == 0) {
showInputMethodPickerLocked();
return ViewRootImpl.EVENT_HANDLED;
return DISPATCH_HANDLED;
}
}
if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
final long startTime = SystemClock.uptimeMillis();
if (mCurChannel != null) {
if (mCurSender == null) {
mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
}
if (mCurSender.sendInputEvent(seq, event)) {
enqueuePendingEventLocked(startTime, seq, mCurId, callback);
return ViewRootImpl.EVENT_PENDING_IME;
} else {
Log.w(TAG, "Unable to send input event to IME: "
+ mCurId + " dropping: " + event);
}
PendingEvent p = obtainPendingEventLocked(
event, token, mCurId, callback, handler);
if (mMainLooper.isCurrentThread()) {
// Already running on the IMM thread so we can send the event immediately.
return sendInputEventOnMainLooperLocked(p);
}
// Post the event to the IMM thread.
Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
msg.setAsynchronous(true);
mH.sendMessage(msg);
return DISPATCH_IN_PROGRESS;
}
}
return ViewRootImpl.EVENT_POST_IME;
return DISPATCH_NOT_HANDLED;
}
void finishedEvent(int seq, boolean handled) {
final FinishedEventCallback callback;
// Must be called on the main looper
void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
final boolean handled;
synchronized (mH) {
PendingEvent p = dequeuePendingEventLocked(seq);
if (p == null) {
int result = sendInputEventOnMainLooperLocked(p);
if (result == DISPATCH_IN_PROGRESS) {
return;
}
handled = (result == DISPATCH_HANDLED);
}
invokeFinishedInputEventCallback(p, handled);
}
// Must be called on the main looper
int sendInputEventOnMainLooperLocked(PendingEvent p) {
if (mCurChannel != null) {
if (mCurSender == null) {
mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
}
final InputEvent event = p.mEvent;
final int seq = event.getSequenceNumber();
if (mCurSender.sendInputEvent(seq, event)) {
mPendingEvents.put(seq, p);
Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
mPendingEvents.size());
Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, p);
msg.setAsynchronous(true);
mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
return DISPATCH_IN_PROGRESS;
}
Log.w(TAG, "Unable to send input event to IME: "
+ mCurId + " dropping: " + event);
}
return DISPATCH_NOT_HANDLED;
}
void finishedInputEvent(int seq, boolean handled, boolean timeout) {
final PendingEvent p;
synchronized (mH) {
int index = mPendingEvents.indexOfKey(seq);
if (index < 0) {
return; // spurious, event already finished or timed out
}
mH.removeMessages(MSG_EVENT_TIMEOUT, p);
callback = p.mCallback;
recyclePendingEventLocked(p);
}
callback.finishedEvent(seq, handled);
}
void timeoutEvent(int seq) {
final FinishedEventCallback callback;
synchronized (mH) {
PendingEvent p = dequeuePendingEventLocked(seq);
if (p == null) {
return; // spurious, event already finished or timed out
}
long delay = SystemClock.uptimeMillis() - p.mStartTime;
Log.w(TAG, "Timeout waiting for IME to handle input event after "
+ delay + "ms: " + p.mInputMethodId);
callback = p.mCallback;
recyclePendingEventLocked(p);
}
callback.finishedEvent(seq, false);
}
p = mPendingEvents.valueAt(index);
mPendingEvents.removeAt(index);
Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
private void enqueuePendingEventLocked(
long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
PendingEvent p = obtainPendingEventLocked(startTime, seq, inputMethodId, callback);
if (mPendingEventTail != null) {
mPendingEventTail.mNext = p;
mPendingEventTail = p;
} else {
mPendingEventHead = p;
mPendingEventTail = p;
}
Message msg = mH.obtainMessage(MSG_EVENT_TIMEOUT, seq, 0, p);
msg.setAsynchronous(true);
mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
}
private PendingEvent dequeuePendingEventLocked(int seq) {
PendingEvent p = mPendingEventHead;
if (p == null) {
return null;
}
if (p.mSeq == seq) {
mPendingEventHead = p.mNext;
if (mPendingEventHead == null) {
mPendingEventTail = null;
}
} else {
PendingEvent prev;
do {
prev = p;
p = p.mNext;
if (p == null) {
return null;
}
} while (p.mSeq != seq);
prev.mNext = p.mNext;
if (mPendingEventTail == p) {
mPendingEventTail = prev;
if (timeout) {
Log.w(TAG, "Timeout waiting for IME to handle input event after "
+ INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
} else {
mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
}
}
p.mNext = null;
return p;
invokeFinishedInputEventCallback(p, handled);
}
private PendingEvent obtainPendingEventLocked(
long startTime, int seq, String inputMethodId, FinishedEventCallback callback) {
PendingEvent p = mPendingEventPool;
if (p != null) {
mPendingEventPoolSize -= 1;
mPendingEventPool = p.mNext;
p.mNext = null;
// Assumes the event has already been removed from the queue.
void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
p.mHandled = handled;
if (p.mHandler.getLooper().isCurrentThread()) {
// Already running on the callback handler thread so we can send the
// callback immediately.
p.run();
} else {
p = new PendingEvent();
}
p.mStartTime = startTime;
p.mSeq = seq;
p.mInputMethodId = inputMethodId;
p.mCallback = callback;
return p;
}
private void recyclePendingEventLocked(PendingEvent p) {
p.mInputMethodId = null;
p.mCallback = null;
if (mPendingEventPoolSize < MAX_PENDING_EVENT_POOL_SIZE) {
mPendingEventPoolSize += 1;
p.mNext = mPendingEventPool;
mPendingEventPool = p;
// Post the event to the callback handler thread.
// In this case, the callback will be responsible for recycling the event.
Message msg = Message.obtain(p.mHandler, p);
msg.setAsynchronous(true);
msg.sendToTarget();
}
}
private void flushPendingEventsLocked() {
mH.removeMessages(MSG_EVENT_TIMEOUT);
mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
PendingEvent p = mPendingEventHead;
while (p != null) {
Message msg = mH.obtainMessage(MSG_EVENT_TIMEOUT, p.mSeq, 0, p);
final int count = mPendingEvents.size();
for (int i = 0; i < count; i++) {
int seq = mPendingEvents.keyAt(i);
Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
msg.setAsynchronous(true);
mH.sendMessage(msg);
p = p.mNext;
msg.sendToTarget();
}
}
private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
PendingEvent p = mPendingEventPool.acquire();
if (p == null) {
p = new PendingEvent();
}
p.mEvent = event;
p.mToken = token;
p.mInputMethodId = inputMethodId;
p.mCallback = callback;
p.mHandler = handler;
return p;
}
private void recyclePendingEventLocked(PendingEvent p) {
p.recycle();
mPendingEventPool.release(p);
}
public void showInputMethodPicker() {
synchronized (mH) {
showInputMethodPickerLocked();
@ -1946,8 +1945,8 @@ public final class InputMethodManager {
* the IME has been finished.
* @hide
*/
public interface FinishedEventCallback {
public void finishedEvent(int seq, boolean handled);
public interface FinishedInputEventCallback {
public void onFinishedInputEvent(Object token, boolean handled);
}
private final class ImeInputEventSender extends InputEventSender {
@ -1957,16 +1956,34 @@ public final class InputMethodManager {
@Override
public void onInputEventFinished(int seq, boolean handled) {
finishedEvent(seq, handled);
finishedInputEvent(seq, handled, false);
}
}
private static final class PendingEvent {
public PendingEvent mNext;
public long mStartTime;
public int mSeq;
private final class PendingEvent implements Runnable {
public InputEvent mEvent;
public Object mToken;
public String mInputMethodId;
public FinishedEventCallback mCallback;
public FinishedInputEventCallback mCallback;
public Handler mHandler;
public boolean mHandled;
public void recycle() {
mEvent = null;
mToken = null;
mInputMethodId = null;
mCallback = null;
mHandler = null;
mHandled = false;
}
@Override
public void run() {
mCallback.onFinishedInputEvent(mToken, mHandled);
synchronized (mH) {
recyclePendingEventLocked(this);
}
}
}
}

View File

@ -97,7 +97,7 @@ public class UniverseBackground extends FrameLayout {
public UniverseBackground(Context context) {
super(context);
setBackgroundColor(0xff000000);
mSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
mSession = WindowManagerGlobal.getWindowSession();
mContent = View.inflate(context, R.layout.universe, null);
addView(mContent);
mContent.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {

View File

@ -22,6 +22,6 @@ package android.view.inputmethod;
public class InputMethodManager_Accessor {
public static void resetInstance() {
InputMethodManager.mInstance = null;
InputMethodManager.sInstance = null;
}
}

View File

@ -35,28 +35,15 @@ public class InputMethodManager_Delegate {
// ---- Overridden methods ----
@LayoutlibDelegate
/*package*/ static InputMethodManager getInstance(Looper mainLooper) {
synchronized (InputMethodManager.mInstanceSync) {
if (InputMethodManager.mInstance != null) {
return InputMethodManager.mInstance;
/*package*/ static InputMethodManager getInstance() {
synchronized (InputMethodManager.class) {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm == null) {
imm = new InputMethodManager(
new BridgeIInputMethodManager(), Looper.getMainLooper());
InputMethodManager.sInstance = imm;
}
InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
mainLooper);
return imm;
}
return InputMethodManager.mInstance;
}
@LayoutlibDelegate
/*package*/ static InputMethodManager getInstance(Context context) {
synchronized (InputMethodManager.mInstanceSync) {
if (InputMethodManager.mInstance != null) {
return InputMethodManager.mInstance;
}
InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
Looper.myLooper());
}
return InputMethodManager.mInstance;
}
}

View File

@ -232,7 +232,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
sCurrentContext = mContext;
// create an InputMethodManager
InputMethodManager.getInstance(Looper.myLooper());
InputMethodManager.getInstance();
LayoutLog currentLog = mParams.getLog();
Bridge.setLog(currentLog);