auto import from //branches/cupcake/...@131421

This commit is contained in:
The Android Open Source Project
2009-02-13 12:57:50 -08:00
parent d24b8183b9
commit da996f390e
202 changed files with 7483 additions and 6101 deletions

View File

@@ -55,8 +55,10 @@ import android.os.Message;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -98,6 +100,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
static final int MSG_UNBIND_METHOD = 3000;
static final int MSG_BIND_METHOD = 3010;
static final long TIME_TO_RECONNECT = 10*1000;
static final int LOG_IMF_FORCE_RECONNECT_IME = 32000;
final Context mContext;
final Handler mHandler;
final SettingsObserver mSettingsObserver;
@@ -247,6 +253,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*/
IInputMethod mCurMethod;
/**
* Time that we last initiated a bind to the input method, to determine
* if we should try to disconnect and reconnect to it.
*/
long mLastBindTime;
/**
* Have we called mCurMethod.bindInput()?
*/
@@ -486,7 +498,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
public void systemReady() {
}
public List<InputMethodInfo> getInputMethodList() {
@@ -571,7 +582,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
private int getShowFlags() {
private int getImeShowFlags() {
int flags = 0;
if (mShowForced) {
flags |= InputMethod.SHOW_FORCED
@@ -582,6 +593,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return flags;
}
private int getAppShowFlags() {
int flags = 0;
if (mShowForced) {
flags |= InputMethodManager.SHOW_FORCED;
} else if (!mShowExplicitlyRequested) {
flags |= InputMethodManager.SHOW_IMPLICIT;
}
return flags;
}
InputBindResult attachNewInputLocked(boolean initial, boolean needResult) {
if (!mBoundToMethod) {
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
@@ -598,7 +619,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
if (mShowRequested) {
if (DEBUG) Log.v(TAG, "Attach new input asks to show input");
showCurrentInputLocked(getShowFlags());
showCurrentInputLocked(getAppShowFlags());
}
return needResult
? new InputBindResult(session.session, mCurId, mCurSeq)
@@ -666,14 +687,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return attachNewInputLocked(initial, needResult);
}
if (mHaveConnection) {
if (mCurMethod != null && !cs.sessionRequested) {
cs.sessionRequested = true;
if (DEBUG) Log.v(TAG, "Creating new session for client " + cs);
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_CREATE_SESSION, mCurMethod,
new MethodCallback(mCurMethod)));
if (mCurMethod != null) {
if (!cs.sessionRequested) {
cs.sessionRequested = true;
if (DEBUG) Log.v(TAG, "Creating new session for client " + cs);
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_CREATE_SESSION, mCurMethod,
new MethodCallback(mCurMethod)));
}
// Return to client, and we will get back with it when
// we have had a session made for it.
return new InputBindResult(null, mCurId, mCurSeq);
} else if (SystemClock.uptimeMillis()
< (mLastBindTime+TIME_TO_RECONNECT)) {
// In this case we have connected to the service, but
// don't yet have its interface. If it hasn't been too
// long since we did the connection, we'll return to
// the client and wait to get the service interface so
// we can report back. If it has been too long, we want
// to fall through so we can try a disconnect/reconnect
// to see if we can get back in touch with the service.
return new InputBindResult(null, mCurId, mCurSeq);
} else {
EventLog.writeEvent(LOG_IMF_FORCE_RECONNECT_IME, mCurMethodId,
SystemClock.uptimeMillis()-mLastBindTime, 0);
}
return new InputBindResult(null, mCurId, mCurSeq);
}
}
@@ -682,6 +720,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
}
if (mHaveConnection) {
mContext.unbindService(this);
mHaveConnection = false;
}
if (mCurToken != null) {
try {
if (DEBUG) Log.v(TAG, "Removing window token: " + mCurToken);
@@ -691,16 +734,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurToken = null;
}
if (mHaveConnection) {
mContext.unbindService(this);
mHaveConnection = false;
}
clearCurMethod();
mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
mCurIntent.setComponent(info.getComponent());
if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE)) {
mLastBindTime = SystemClock.uptimeMillis();
mHaveConnection = true;
mCurId = info.getId();
mCurToken = new Binder();
@@ -758,7 +797,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
void onSessionCreated(IInputMethod method, IInputMethodSession session) {
synchronized (mMethodMap) {
if (mCurMethod == method) {
if (mCurMethod != null && method != null
&& mCurMethod.asBinder() == method.asBinder()) {
if (mCurClient != null) {
mCurClient.curSession = new SessionState(mCurClient,
method, session);
@@ -781,6 +821,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
mCurMethod = null;
}
mStatusBar.setIconVisibility(mInputMethodIcon, false);
}
public void onServiceDisconnected(ComponentName name) {
@@ -790,6 +831,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (mCurMethod != null && mCurIntent != null
&& name.equals(mCurIntent.getComponent())) {
clearCurMethod();
// We consider this to be a new bind attempt, since the system
// should now try to restart the service for us.
mLastBindTime = SystemClock.uptimeMillis();
mShowRequested = mInputShown;
mInputShown = false;
if (mCurClient != null) {
@@ -800,23 +844,28 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
public void updateStatusIcon(int iconId, String iconPackage) {
if (iconId == 0) {
Log.d(TAG, "hide the small icon for the input method");
mStatusBar.setIconVisibility(mInputMethodIcon, false);
} else {
Log.d(TAG, "show a small icon for the input method");
if (iconPackage != null
&& iconPackage
.equals(InputMethodManager.BUILDIN_INPUTMETHOD_PACKAGE)) {
iconPackage = null;
public void updateStatusIcon(IBinder token, String packageName, int iconId) {
long ident = Binder.clearCallingIdentity();
try {
if (token == null || mCurToken != token) {
Log.w(TAG, "Ignoring setInputMethod of token: " + token);
return;
}
mInputMethodData.iconId = iconId;
mInputMethodData.iconPackage = iconPackage;
mStatusBar.updateIcon(mInputMethodIcon, mInputMethodData, null);
mStatusBar.setIconVisibility(mInputMethodIcon, true);
synchronized (mMethodMap) {
if (iconId == 0) {
if (DEBUG) Log.d(TAG, "hide the small icon for the input method");
mStatusBar.setIconVisibility(mInputMethodIcon, false);
} else if (packageName != null) {
if (DEBUG) Log.d(TAG, "show a small icon for the input method");
mInputMethodData.iconId = iconId;
mInputMethodData.iconPackage = packageName;
mStatusBar.updateIcon(mInputMethodIcon, mInputMethodData, null);
mStatusBar.setIconVisibility(mInputMethodIcon, true);
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@@ -860,23 +909,28 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
public void showSoftInput(IInputMethodClient client, int flags) {
synchronized (mMethodMap) {
if (mCurClient == null || client == null
|| mCurClient.client.asBinder() != client.asBinder()) {
try {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring showSoftInput of: " + client);
return;
long ident = Binder.clearCallingIdentity();
try {
synchronized (mMethodMap) {
if (mCurClient == null || client == null
|| mCurClient.client.asBinder() != client.asBinder()) {
try {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring showSoftInput of: " + client);
return;
}
} catch (RemoteException e) {
}
} catch (RemoteException e) {
}
if (DEBUG) Log.v(TAG, "Client requesting input be shown");
showCurrentInputLocked(flags);
}
if (DEBUG) Log.v(TAG, "Client requesting input be shown");
showCurrentInputLocked(flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@@ -891,29 +945,44 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
if (mCurMethod != null) {
executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
MSG_SHOW_SOFT_INPUT, getShowFlags(), mCurMethod));
MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod));
mInputShown = true;
} else if (mHaveConnection && SystemClock.uptimeMillis()
< (mLastBindTime+TIME_TO_RECONNECT)) {
// The client has asked to have the input method shown, but
// we have been sitting here too long with a connection to the
// service and no interface received, so let's disconnect/connect
// to try to prod things along.
EventLog.writeEvent(LOG_IMF_FORCE_RECONNECT_IME, mCurMethodId,
SystemClock.uptimeMillis()-mLastBindTime,1);
mContext.unbindService(this);
mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE);
}
}
public void hideSoftInput(IInputMethodClient client, int flags) {
synchronized (mMethodMap) {
if (mCurClient == null || client == null
|| mCurClient.client.asBinder() != client.asBinder()) {
try {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring hideSoftInput of: " + client);
return;
long ident = Binder.clearCallingIdentity();
try {
synchronized (mMethodMap) {
if (mCurClient == null || client == null
|| mCurClient.client.asBinder() != client.asBinder()) {
try {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring hideSoftInput of: " + client);
return;
}
} catch (RemoteException e) {
}
} catch (RemoteException e) {
}
if (DEBUG) Log.v(TAG, "Client requesting input be hidden");
hideCurrentInputLocked(flags);
}
if (DEBUG) Log.v(TAG, "Client requesting input be hidden");
hideCurrentInputLocked(flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@@ -942,70 +1011,75 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
public void windowGainedFocus(IInputMethodClient client,
boolean viewHasFocus, boolean isTextEditor, int softInputMode,
boolean first, int windowFlags) {
synchronized (mMethodMap) {
if (DEBUG) Log.v(TAG, "windowGainedFocus: " + client.asBinder()
+ " viewHasFocus=" + viewHasFocus
+ " isTextEditor=" + isTextEditor
+ " softInputMode=#" + Integer.toHexString(softInputMode)
+ " first=" + first + " flags=#"
+ Integer.toHexString(windowFlags));
if (mCurClient == null || client == null
|| mCurClient.client.asBinder() != client.asBinder()) {
try {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring focus gain of: " + client);
return;
long ident = Binder.clearCallingIdentity();
try {
synchronized (mMethodMap) {
if (DEBUG) Log.v(TAG, "windowGainedFocus: " + client.asBinder()
+ " viewHasFocus=" + viewHasFocus
+ " isTextEditor=" + isTextEditor
+ " softInputMode=#" + Integer.toHexString(softInputMode)
+ " first=" + first + " flags=#"
+ Integer.toHexString(windowFlags));
if (mCurClient == null || client == null
|| mCurClient.client.asBinder() != client.asBinder()) {
try {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring focus gain of: " + client);
return;
}
} catch (RemoteException e) {
}
} catch (RemoteException e) {
}
switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
if (!isTextEditor || (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
!= WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
// There is no focus view, and this window will
// be behind any soft input window, so hide the
// soft input window if it is shown.
if (DEBUG) Log.v(TAG, "Unspecified window will hide input");
hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS);
}
} else if (isTextEditor && (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
== WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
&& (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
// There is a focus view, and we are navigating forward
// into the window, so show the input window for the user.
if (DEBUG) Log.v(TAG, "Unspecified window will show input");
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
// Do nothing.
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
if (DEBUG) Log.v(TAG, "Window asks to hide input");
hideCurrentInputLocked(0);
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
if ((softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
if (DEBUG) Log.v(TAG, "Window asks to show input going forward");
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
if (DEBUG) Log.v(TAG, "Window asks to always show input");
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
break;
}
}
switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
if (!isTextEditor || (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
!= WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
// There is no focus view, and this window will
// be behind any soft input window, so hide the
// soft input window if it is shown.
if (DEBUG) Log.v(TAG, "Unspecified window will hide input");
hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS);
}
} else if (isTextEditor && (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
== WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
&& (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
// There is a focus view, and we are navigating forward
// into the window, so show the input window for the user.
if (DEBUG) Log.v(TAG, "Unspecified window will show input");
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
// Do nothing.
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
if (DEBUG) Log.v(TAG, "Window asks to hide input");
hideCurrentInputLocked(0);
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
if ((softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
if (DEBUG) Log.v(TAG, "Window asks to show input going forward");
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
if (DEBUG) Log.v(TAG, "Window asks to always show input");
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
break;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@@ -1022,7 +1096,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
public void setInputMethod(IBinder token, String id) {
synchronized (mMethodMap) {
if (mCurToken == null) {
if (token == null) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.WRITE_SECURE_SETTINGS)
!= PackageManager.PERMISSION_GRANTED) {
@@ -1032,19 +1106,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
} else if (mCurToken != token) {
Log.w(TAG, "Ignoring setInputMethod of token: " + token);
return;
}
setInputMethodLocked(id);
long ident = Binder.clearCallingIdentity();
try {
setInputMethodLocked(id);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
public void hideMySoftInput(IBinder token, int flags) {
synchronized (mMethodMap) {
if (mCurToken == null || mCurToken != token) {
if (token == null || mCurToken != token) {
Log.w(TAG, "Ignoring hideInputMethod of token: " + token);
return;
}
hideCurrentInputLocked(flags);
long ident = Binder.clearCallingIdentity();
try {
hideCurrentInputLocked(flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
@@ -1209,7 +1295,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// ----------------------------------------------------------------------
public void showInputMethodMenu() {
void showInputMethodMenu() {
if (DEBUG) Log.v(TAG, "Show switching menu");
hideInputMethodMenu();
@@ -1309,83 +1395,88 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
+ android.Manifest.permission.WRITE_SECURE_SETTINGS);
}
// Make sure this is a valid input method.
InputMethodInfo imm = mMethodMap.get(id);
if (imm == null) {
long ident = Binder.clearCallingIdentity();
try {
// Make sure this is a valid input method.
InputMethodInfo imm = mMethodMap.get(id);
if (imm == null) {
throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
}
}
StringBuilder builder = new StringBuilder(256);
boolean removed = false;
String firstId = null;
// Look through the currently enabled input methods.
String enabledStr = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.ENABLED_INPUT_METHODS);
if (enabledStr != null) {
final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
splitter.setString(enabledStr);
while (splitter.hasNext()) {
String curId = splitter.next();
if (curId.equals(id)) {
if (enabled) {
// We are enabling this input method, but it is
// already enabled. Nothing to do. The previous
// state was enabled.
return true;
}
// We are disabling this input method, and it is
// currently enabled. Skip it to remove from the
// new list.
removed = true;
} else if (!enabled) {
// We are building a new list of input methods that
// doesn't contain the given one.
if (firstId == null) firstId = curId;
if (builder.length() > 0) builder.append(':');
builder.append(curId);
if (imm == null) {
throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
}
}
}
if (!enabled) {
if (!removed) {
// We are disabling the input method but it is already
// disabled. Nothing to do. The previous state was
// disabled.
return false;
StringBuilder builder = new StringBuilder(256);
boolean removed = false;
String firstId = null;
// Look through the currently enabled input methods.
String enabledStr = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.ENABLED_INPUT_METHODS);
if (enabledStr != null) {
final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
splitter.setString(enabledStr);
while (splitter.hasNext()) {
String curId = splitter.next();
if (curId.equals(id)) {
if (enabled) {
// We are enabling this input method, but it is
// already enabled. Nothing to do. The previous
// state was enabled.
return true;
}
// We are disabling this input method, and it is
// currently enabled. Skip it to remove from the
// new list.
removed = true;
} else if (!enabled) {
// We are building a new list of input methods that
// doesn't contain the given one.
if (firstId == null) firstId = curId;
if (builder.length() > 0) builder.append(':');
builder.append(curId);
}
}
}
// Update the setting with the new list of input methods.
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
// We the disabled input method is currently selected, switch
// to another one.
String selId = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD);
if (id.equals(selId)) {
if (!enabled) {
if (!removed) {
// We are disabling the input method but it is already
// disabled. Nothing to do. The previous state was
// disabled.
return false;
}
// Update the setting with the new list of input methods.
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD,
firstId != null ? firstId : "");
Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
// We the disabled input method is currently selected, switch
// to another one.
String selId = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD);
if (id.equals(selId)) {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD,
firstId != null ? firstId : "");
}
// Previous state was enabled.
return true;
}
// Previous state was enabled.
return true;
// Add in the newly enabled input method.
if (enabledStr == null || enabledStr.length() == 0) {
enabledStr = id;
} else {
enabledStr = enabledStr + ':' + id;
}
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ENABLED_INPUT_METHODS, enabledStr);
// Previous state was disabled.
return false;
} finally {
Binder.restoreCallingIdentity(ident);
}
// Add in the newly enabled input method.
if (enabledStr == null || enabledStr.length() == 0) {
enabledStr = id;
} else {
enabledStr = enabledStr + ':' + id;
}
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ENABLED_INPUT_METHODS, enabledStr);
// Previous state was disabled.
return false;
}
}