部分调用栈信息:
01-01 04:59:23.234 W/System.err( 930): java.lang.Throwable: stack dump 01-01 04:59:23.235 W/System.err( 930): at java.lang.Thread.dumpStack(Thread.java:489) 01-01 04:59:23.235 W/System.err( 930): at android.service.textservice.SpellCheckerService$InternalISpellCheckerSession.onGetSentenceSuggestionsMultiple(SpellCheckerService.java:271) 01-01 04:59:23.235 W/System.err( 930): at com.android.internal.textservice.ISpellCheckerSession$Stub.onTransact(ISpellCheckerSession.java:67) 01-01 04:59:23.235 W/System.err( 930): at android.os.Binder.execTransact(Binder.java:404) 01-01 04:59:23.235 W/System.err( 930): at dalvik.system.NativeStart.run(Native Method) 01-01 04:59:23.506 W/System.err( 1415): java.lang.Throwable: stack dump 01-01 04:59:23.506 W/System.err( 1415): at java.lang.Thread.dumpStack(Thread.java:489) 01-01 04:59:23.507 W/System.err( 1415): at android.widget.SpellChecker.onGetSentenceSuggestions(SpellChecker.java:413) 01-01 04:59:23.507 W/System.err( 1415): at android.view.textservice.SpellCheckerSession.handleOnGetSentenceSuggestionsMultiple(SpellCheckerSession.java:221) 01-01 04:59:23.507 W/System.err( 1415): at android.view.textservice.SpellCheckerSession.access$100(SpellCheckerSession.java:86) 01-01 04:59:23.507 W/System.err( 1415): at android.view.textservice.SpellCheckerSession$1.handleMessage(SpellCheckerSession.java:116) 01-01 04:59:23.507 W/System.err( 1415): at android.os.Handler.dispatchMessage(Handler.java:110) 01-01 04:59:23.508 W/System.err( 1415): at android.os.Looper.loop(Looper.java:193) 01-01 04:59:23.508 W/System.err( 1415): at android.app.ActivityThread.main(ActivityThread.java:5299) 01-01 04:59:23.508 W/System.err( 1415): at java.lang.reflect.Method.invokeNative(Native Method) 01-01 04:59:23.508 W/System.err( 1415): at java.lang.reflect.Method.invoke(Method.java:515) 01-01 04:59:23.509 W/System.err( 1415): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825) 01-01 04:59:23.511 W/System.err( 1415): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641) 01-01 04:59:23.511 W/System.err( 1415): at dalvik.system.NativeStart.main(Native Method)
SpellChecker/SpellCheckerSession/TextServicesManager/SpellCheckerService/TextServicesManagerService 之间的关系
SpellChecker的主要工作是将自己作为callback,注册到新建的SpellCheckerSession中去,它实现了SpellCheckerSessionListener
在SpellChecker中遇到需要分析的单词,使用SpellCheckerSession来异步的获取SuggestionsInfo,通过callback中获取结果然后传递给Editor最总显示到界面上去
SpellCheckerSession通过TextServicesManager来获取(同时注册SpellChecker作为callback),这个过程没有IPC发生;
SpellCheckerSession实际上是一个Wrapper,由SpellCheckerSessionListenerImpl来负责具体的工作,而其中包含一个ISpellCheckerSession,
工作实际上又是由ISpellCheckerSession进行处理的,ISpellCheckerSession需要IPC来进行初始化。
SpellCheckerSessionListenerImpl实现ISpellCheckerSessionListener,根据dumpStack即是SpellCheckerSessionListenerImpl的方法被调用
最终SpellChecker的callback被调用。
InternalListener实现了ITextServicesSessionListener并将SpellCheckerSessionListenerImpl包含在其中,ISpellCheckerSession的初始化就由它来做。<<- initialize here
而具体过程在TextServicesManager中
TextServicesManager有以下作用
* The text services manager as expressed by this class
* is the central point of the system that manages interaction between all
* other parts. It is expressed as the client-side API here which exists
* in each application context and communicates with a global system service
* that manages the interaction across all processes.
* A text service implements a particular
* interaction model allowing the client application to retrieve information of text.
* The system binds to the current text service that is in use, causing it to be created and run.
* <li> Multiple <strong>client applications</strong> arbitrate with the text service
* manager for connections to text services.
*
* <h3>Text services sessions</h3>
* <ul>
* <li>The <strong>spell checker session</strong> is one of the text services.
private static ITextServicesManager sService; ... private TextServicesManager() { if (sService == null) { IBinder b = ServiceManager.getService(Context.TEXT_SERVICES_MANAGER_SERVICE); sService = ITextServicesManager.Stub.asInterface(b); } } ... final SpellCheckerSession session = new SpellCheckerSession( sci, sService, listener, subtypeInUse); try { sService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(), session.getTextServicesSessionListener(), session.getSpellCheckerSessionListener(), bundle); } catch (RemoteException e) { return null; }
@Override public void getSpellCheckerService(String sciId, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener, Bundle bundle) { if (!calledFromValidUser()) { return; } if (!mSystemReady) { return; } if (TextUtils.isEmpty(sciId) || tsListener == null || scListener == null) { Slog.e(TAG, "getSpellCheckerService: Invalid input."); return; } synchronized(mSpellCheckerMap) { if (!mSpellCheckerMap.containsKey(sciId)) { return; } final SpellCheckerInfo sci = mSpellCheckerMap.get(sciId); 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, uid, bundle); if (recipient == null) { if (DBG) { Slog.w(TAG, "Didn't create a death recipient."); } return; } if (bindGroup.mSpellChecker == null & bindGroup.mConnected) { Slog.e(TAG, "The state of the spell checker bind group is illegal."); bindGroup.removeAll(); } else if (bindGroup.mSpellChecker != null) { if (DBG) { Slog.w(TAG, "Existing bind found. Return a spell checker session now. " + "Listeners count = " + bindGroup.mListeners.size()); } try { final ISpellCheckerSession session = bindGroup.mSpellChecker.getISpellCheckerSession( <<- 针对mSpellCheckerBindGroups能找到对应IME Spell Checker服务,就从缓存中获取 recipient.mScLocale, recipient.mScListener, bundle); if (session != null) { tsListener.onServiceConnected(session); <<- 针对mSpellCheckerBindGroups能找到对应IME Spell Checker服务,同时去初始化SpellCheckerSession中的mISpellCheckerSession 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(); } } } } final long ident = Binder.clearCallingIdentity(); try { startSpellCheckerServiceInnerLocked( <<- 针对mSpellCheckerBindGroups还没有的情况,要进行bind IME Spell Checker服务 sci, locale, tsListener, scListener, uid, bundle); } finally { Binder.restoreCallingIdentity(ident); } } return; }
W/TextServicesManagerService( 703): Start spell checker session inner locked. W/TextServicesManagerService( 703): bind service: com.android.inputmethod.latin/.spellcheck.AndroidSpellCheckerService W/SpellCheckerService( 880): onBind W/TextServicesManagerService( 703): onServiceConnected: ComponentInfo{com.android.inputmethod.latin/com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService}
向IME Spell Checker服务注册ISpellCheckerSessionListener的过程:
IME的Spell Checker在被onBind后会返回一个SpellCheckerServiceBinder -> TextServicesManagerService.InternalServiceConnection.onServiceConnected -> InternalServiceConnection.onServiceConnectedInnerLocked -> SpellCheckerBindGroup.onServiceConnected -> 将ISpellCheckerSessionListener注册过去,即SpellCheckerSession中的SpellCheckerSessionListenerImpl