Fix issues in TextServicesManagerService

Change-Id: I48c81226d824e8aad42e01e87fcf9a5b466d2321
This commit is contained in:
satok
2011-07-29 18:38:21 +09:00
parent 6be6d7548f
commit df5659d3d3
2 changed files with 79 additions and 32 deletions

View File

@@ -73,6 +73,16 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
synchronized (mSpellCheckerMap) {
buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
}
SpellCheckerInfo sci = getCurrentSpellChecker(null);
if (sci == null) {
sci = findAvailSpellCheckerLocked(null, null);
if (sci != null) {
// Set the current spell checker if there is one or more spell checkers
// available. In this case, "sci" is the first one in the available spell
// checkers.
setCurrentSpellCheckerLocked(sci);
}
}
}
private class TextServicesMonitor extends PackageMonitor {
@@ -87,10 +97,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
final int change = isPackageDisappearing(packageName);
if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
// Package disappearing
setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
} else if (isPackageModified(packageName)) {
// Package modified
setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
}
}
}
@@ -160,13 +170,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
}
if (TextUtils.isEmpty(curSpellCheckerId)) {
final SpellCheckerInfo sci = findAvailSpellCheckerLocked(null, null);
if (sci == null) return null;
// Set the current spell checker if there is one or more spell checkers
// available. In this case, "sci" is the first one in the available spell
// checkers.
setCurrentSpellChecker(sci);
return sci;
return null;
}
return mSpellCheckerMap.get(curSpellCheckerId);
}
@@ -187,12 +191,13 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
if (!mSpellCheckerMap.containsKey(sciId)) {
return;
}
final int uid = Binder.getCallingUid();
if (mSpellCheckerBindGroups.containsKey(sciId)) {
final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId);
if (bindGroup != null) {
final InternalDeathRecipient recipient =
mSpellCheckerBindGroups.get(sciId).addListener(
tsListener, locale, scListener);
tsListener, locale, scListener, uid);
if (recipient == null) {
if (DBG) {
Slog.w(TAG, "Didn't create a death recipient.");
@@ -204,14 +209,22 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
bindGroup.removeAll();
} else if (bindGroup.mSpellChecker != null) {
if (DBG) {
Slog.w(TAG, "Existing bind found. Return a spell checker session now.");
Slog.w(TAG, "Existing bind found. Return a spell checker session now. "
+ "Listeners count = " + bindGroup.mListeners.size());
}
try {
final ISpellCheckerSession session =
bindGroup.mSpellChecker.getISpellCheckerSession(
recipient.mScLocale, recipient.mScListener);
tsListener.onServiceConnected(session);
return;
if (session != null) {
tsListener.onServiceConnected(session);
return;
} else {
if (DBG) {
Slog.w(TAG, "Existing bind already expired. ");
}
bindGroup.removeAll();
}
} catch (RemoteException e) {
Slog.e(TAG, "Exception in getting spell checker session: " + e);
bindGroup.removeAll();
@@ -221,7 +234,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
final long ident = Binder.clearCallingIdentity();
try {
startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener);
startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -230,7 +243,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) {
ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
int uid) {
if (DBG) {
Slog.w(TAG, "Start spell checker session inner locked.");
}
final String sciId = info.getId();
final InternalServiceConnection connection = new InternalServiceConnection(
sciId, locale, scListener);
@@ -244,7 +261,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
return;
}
final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
connection, tsListener, locale, scListener);
connection, tsListener, locale, scListener, uid);
mSpellCheckerBindGroups.put(sciId, group);
}
@@ -272,19 +289,39 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
}
private void setCurrentSpellChecker(SpellCheckerInfo sci) {
@Override
public void setCurrentSpellChecker(SpellCheckerInfo sci) {
synchronized(mSpellCheckerMap) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.WRITE_SECURE_SETTINGS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
"Requires permission "
+ android.Manifest.permission.WRITE_SECURE_SETTINGS);
}
setCurrentSpellCheckerLocked(sci);
}
}
private void setCurrentSpellCheckerLocked(SpellCheckerInfo sci) {
if (DBG) {
Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId());
}
if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return;
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
if (sci == null || !mSpellCheckerMap.containsKey(sci.getId())) return;
final long ident = Binder.clearCallingIdentity();
try {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
} finally {
Binder.restoreCallingIdentity(ident);
}
}
// SpellCheckerBindGroup contains active text service session listeners.
// If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
// mSpellCheckerBindGroups
private class SpellCheckerBindGroup {
private final String TAG = SpellCheckerBindGroup.class.getSimpleName();
private final InternalServiceConnection mInternalConnection;
private final ArrayList<InternalDeathRecipient> mListeners =
new ArrayList<InternalDeathRecipient>();
@@ -293,10 +330,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public SpellCheckerBindGroup(InternalServiceConnection connection,
ITextServicesSessionListener listener, String locale,
ISpellCheckerSessionListener scListener) {
ISpellCheckerSessionListener scListener, int uid) {
mInternalConnection = connection;
mConnected = false;
addListener(listener, locale, scListener);
addListener(listener, locale, scListener, uid);
}
public void onServiceConnected(ISpellCheckerService spellChecker) {
@@ -310,7 +347,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
listener.mScLocale, listener.mScListener);
listener.mTsListener.onServiceConnected(session);
} catch (RemoteException e) {
Slog.e(TAG, "Exception in getting spell checker session: " + e);
Slog.e(TAG, "Exception in getting the spell checker session: " + e);
removeAll();
return;
}
@@ -321,7 +358,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener,
String locale, ISpellCheckerSessionListener scListener) {
String locale, ISpellCheckerSessionListener scListener, int uid) {
if (DBG) {
Slog.d(TAG, "addListener: " + locale);
}
@@ -336,10 +373,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
}
recipient = new InternalDeathRecipient(
this, tsListener, locale, scListener);
this, tsListener, locale, scListener, uid);
scListener.asBinder().linkToDeath(recipient, 0);
mListeners.add(new InternalDeathRecipient(
this, tsListener, locale, scListener));
mListeners.add(recipient);
} catch(RemoteException e) {
// do nothing
}
@@ -350,7 +386,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public void removeListener(ISpellCheckerSessionListener listener) {
if (DBG) {
Slog.d(TAG, "remove listener");
Slog.w(TAG, "remove listener: " + listener.hashCode());
}
synchronized(mSpellCheckerMap) {
final int size = mListeners.size();
@@ -359,11 +395,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
for (int i = 0; i < size; ++i) {
final InternalDeathRecipient tempRecipient = mListeners.get(i);
if(tempRecipient.hasSpellCheckerListener(listener)) {
if (DBG) {
Slog.w(TAG, "found existing listener.");
}
removeList.add(tempRecipient);
}
}
final int removeSize = removeList.size();
for (int i = 0; i < removeSize; ++i) {
if (DBG) {
Slog.w(TAG, "Remove " + removeList.get(i));
}
mListeners.remove(removeList.get(i));
}
cleanLocked();
@@ -385,8 +427,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public void removeAll() {
Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
mListeners.clear();
cleanLocked();
synchronized(mSpellCheckerMap) {
mListeners.clear();
cleanLocked();
}
}
}
@@ -426,17 +470,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public final ISpellCheckerSessionListener mScListener;
public final String mScLocale;
private final SpellCheckerBindGroup mGroup;
public final int mUid;
public InternalDeathRecipient(SpellCheckerBindGroup group,
ITextServicesSessionListener tsListener, String scLocale,
ISpellCheckerSessionListener scListener) {
ISpellCheckerSessionListener scListener, int uid) {
mTsListener = tsListener;
mScListener = scListener;
mScLocale = scLocale;
mGroup = group;
mUid = uid;
}
public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
return mScListener.equals(listener);
return listener.asBinder().equals(mScListener.asBinder());
}
@Override