TextServicesManagerService.java revision 2cf1cf098513807ffd3420ae106f438e943d0cd8
1988323c57bd25a58f05dfa492d9b9c8ab62c5153satok/* 2988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * Copyright (C) 2011 The Android Open Source Project 3988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * 4988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * Licensed under the Apache License, Version 2.0 (the "License"); 5988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * you may not use this file except in compliance with the License. 6988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * You may obtain a copy of the License at 7988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * 8988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * http://www.apache.org/licenses/LICENSE-2.0 9988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * 10988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * Unless required by applicable law or agreed to in writing, software 11988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * distributed under the License is distributed on an "AS IS" BASIS, 12988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * See the License for the specific language governing permissions and 14988323c57bd25a58f05dfa492d9b9c8ab62c5153satok * limitations under the License. 15988323c57bd25a58f05dfa492d9b9c8ab62c5153satok */ 16988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 17988323c57bd25a58f05dfa492d9b9c8ab62c5153satokpackage com.android.server; 18988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 19988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport com.android.internal.content.PackageMonitor; 20988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport com.android.internal.textservice.ISpellCheckerService; 21988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport com.android.internal.textservice.ISpellCheckerSession; 22988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport com.android.internal.textservice.ISpellCheckerSessionListener; 23988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport com.android.internal.textservice.ITextServicesManager; 24988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport com.android.internal.textservice.ITextServicesSessionListener; 25988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 2603b2ea1102d9e3e9f189173878706ab04533eea3satokimport org.xmlpull.v1.XmlPullParserException; 2703b2ea1102d9e3e9f189173878706ab04533eea3satok 28988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.content.ComponentName; 29988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.content.Context; 30988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.content.Intent; 31988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.content.ServiceConnection; 32988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.content.pm.PackageManager; 33988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.content.pm.ResolveInfo; 34988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.content.pm.ServiceInfo; 356be6d7548fb7c29a4d46dc985318ab2adf69f95fsatokimport android.os.Binder; 365357806980269d846a15c845a6fcc0384fb18860satokimport android.os.Bundle; 37988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.os.IBinder; 38988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.os.RemoteException; 39988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.provider.Settings; 40988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.service.textservice.SpellCheckerService; 415357806980269d846a15c845a6fcc0384fb18860satokimport android.text.TextUtils; 42988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.util.Slog; 43988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport android.view.textservice.SpellCheckerInfo; 44ada8c4e6a3da96a795f39a1028d448eb7aebfab3satokimport android.view.textservice.SpellCheckerSubtype; 45988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 4671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackbornimport java.io.FileDescriptor; 4703b2ea1102d9e3e9f189173878706ab04533eea3satokimport java.io.IOException; 4871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackbornimport java.io.PrintWriter; 49988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport java.util.ArrayList; 50988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport java.util.HashMap; 51988323c57bd25a58f05dfa492d9b9c8ab62c5153satokimport java.util.List; 5271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackbornimport java.util.Map; 53988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 54988323c57bd25a58f05dfa492d9b9c8ab62c5153satokpublic class TextServicesManagerService extends ITextServicesManager.Stub { 55988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private static final String TAG = TextServicesManagerService.class.getSimpleName(); 56988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private static final boolean DBG = false; 57988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 58988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final Context mContext; 59988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private boolean mSystemReady; 60988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final TextServicesMonitor mMonitor; 61988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap = 62988323c57bd25a58f05dfa492d9b9c8ab62c5153satok new HashMap<String, SpellCheckerInfo>(); 63988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<SpellCheckerInfo>(); 64988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups = 65988323c57bd25a58f05dfa492d9b9c8ab62c5153satok new HashMap<String, SpellCheckerBindGroup>(); 66988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 67988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void systemReady() { 68988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (!mSystemReady) { 69988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mSystemReady = true; 70988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 71988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 72988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 73988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public TextServicesManagerService(Context context) { 74988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mSystemReady = false; 75988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mContext = context; 76988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mMonitor = new TextServicesMonitor(); 77988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mMonitor.register(context, true); 78988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized (mSpellCheckerMap) { 79988323c57bd25a58f05dfa492d9b9c8ab62c5153satok buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap); 80988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 81df5659d3d317b5cf351baffe3e0d4876e89678bfsatok SpellCheckerInfo sci = getCurrentSpellChecker(null); 82df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (sci == null) { 83df5659d3d317b5cf351baffe3e0d4876e89678bfsatok sci = findAvailSpellCheckerLocked(null, null); 84df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (sci != null) { 85df5659d3d317b5cf351baffe3e0d4876e89678bfsatok // Set the current spell checker if there is one or more spell checkers 86df5659d3d317b5cf351baffe3e0d4876e89678bfsatok // available. In this case, "sci" is the first one in the available spell 87df5659d3d317b5cf351baffe3e0d4876e89678bfsatok // checkers. 885b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok setCurrentSpellCheckerLocked(sci.getId()); 89df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 90df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 91988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 92988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 93988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private class TextServicesMonitor extends PackageMonitor { 94988323c57bd25a58f05dfa492d9b9c8ab62c5153satok @Override 95988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void onSomePackagesChanged() { 96988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized (mSpellCheckerMap) { 97988323c57bd25a58f05dfa492d9b9c8ab62c5153satok buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap); 98988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // TODO: Update for each locale 99988323c57bd25a58f05dfa492d9b9c8ab62c5153satok SpellCheckerInfo sci = getCurrentSpellChecker(null); 100da317ef68603dc7649f98bda495267973825e7fasatok if (sci == null) return; 101988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final String packageName = sci.getPackageName(); 102988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final int change = isPackageDisappearing(packageName); 1035b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok if (// Package disappearing 1045b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE 1055b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok // Package modified 1065b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok || isPackageModified(packageName)) { 1075b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok sci = findAvailSpellCheckerLocked(null, packageName); 1085b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok if (sci != null) { 1095b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok setCurrentSpellCheckerLocked(sci.getId()); 1105b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok } 111988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 112988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 113988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 114988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 115988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 116988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private static void buildSpellCheckerMapLocked(Context context, 117988323c57bd25a58f05dfa492d9b9c8ab62c5153satok ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map) { 118988323c57bd25a58f05dfa492d9b9c8ab62c5153satok list.clear(); 119988323c57bd25a58f05dfa492d9b9c8ab62c5153satok map.clear(); 120988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final PackageManager pm = context.getPackageManager(); 121988323c57bd25a58f05dfa492d9b9c8ab62c5153satok List<ResolveInfo> services = pm.queryIntentServices( 122988323c57bd25a58f05dfa492d9b9c8ab62c5153satok new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA); 123988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final int N = services.size(); 124988323c57bd25a58f05dfa492d9b9c8ab62c5153satok for (int i = 0; i < N; ++i) { 125988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final ResolveInfo ri = services.get(i); 126988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final ServiceInfo si = ri.serviceInfo; 127988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final ComponentName compName = new ComponentName(si.packageName, si.name); 128988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (!android.Manifest.permission.BIND_TEXT_SERVICE.equals(si.permission)) { 129988323c57bd25a58f05dfa492d9b9c8ab62c5153satok Slog.w(TAG, "Skipping text service " + compName 130988323c57bd25a58f05dfa492d9b9c8ab62c5153satok + ": it does not require the permission " 131988323c57bd25a58f05dfa492d9b9c8ab62c5153satok + android.Manifest.permission.BIND_TEXT_SERVICE); 132988323c57bd25a58f05dfa492d9b9c8ab62c5153satok continue; 133988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 134988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (DBG) Slog.d(TAG, "Add: " + compName); 13503b2ea1102d9e3e9f189173878706ab04533eea3satok try { 13603b2ea1102d9e3e9f189173878706ab04533eea3satok final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri); 1373cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok if (sci.getSubtypeCount() <= 0) { 1383cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok Slog.w(TAG, "Skipping text service " + compName 1393cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok + ": it does not contain subtypes."); 1403cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok continue; 1413cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok } 14203b2ea1102d9e3e9f189173878706ab04533eea3satok list.add(sci); 14303b2ea1102d9e3e9f189173878706ab04533eea3satok map.put(sci.getId(), sci); 14403b2ea1102d9e3e9f189173878706ab04533eea3satok } catch (XmlPullParserException e) { 14503b2ea1102d9e3e9f189173878706ab04533eea3satok Slog.w(TAG, "Unable to load the spell checker " + compName, e); 14603b2ea1102d9e3e9f189173878706ab04533eea3satok } catch (IOException e) { 14703b2ea1102d9e3e9f189173878706ab04533eea3satok Slog.w(TAG, "Unable to load the spell checker " + compName, e); 14803b2ea1102d9e3e9f189173878706ab04533eea3satok } 149988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 150da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 151da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "buildSpellCheckerMapLocked: " + list.size() + "," + map.size()); 152da317ef68603dc7649f98bda495267973825e7fasatok } 153988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 154988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 155988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // TODO: find an appropriate spell checker for specified locale 156988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private SpellCheckerInfo findAvailSpellCheckerLocked(String locale, String prefPackage) { 157988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final int spellCheckersCount = mSpellCheckerList.size(); 158988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (spellCheckersCount == 0) { 159988323c57bd25a58f05dfa492d9b9c8ab62c5153satok Slog.w(TAG, "no available spell checker services found"); 160988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return null; 161988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 162988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (prefPackage != null) { 163988323c57bd25a58f05dfa492d9b9c8ab62c5153satok for (int i = 0; i < spellCheckersCount; ++i) { 164988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final SpellCheckerInfo sci = mSpellCheckerList.get(i); 165988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (prefPackage.equals(sci.getPackageName())) { 166da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 167da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "findAvailSpellCheckerLocked: " + sci.getPackageName()); 168da317ef68603dc7649f98bda495267973825e7fasatok } 169988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return sci; 170988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 171988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 172988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 173988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (spellCheckersCount > 1) { 174988323c57bd25a58f05dfa492d9b9c8ab62c5153satok Slog.w(TAG, "more than one spell checker service found, picking first"); 175988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 176988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return mSpellCheckerList.get(0); 177988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 178988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 179988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // TODO: Save SpellCheckerService by supported languages. Currently only one spell 180988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // checker is saved. 181988323c57bd25a58f05dfa492d9b9c8ab62c5153satok @Override 182988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public SpellCheckerInfo getCurrentSpellChecker(String locale) { 183988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized (mSpellCheckerMap) { 184a33c4fc5bed76727f1e06e522e0136101a2304cdsatok final String curSpellCheckerId = 185988323c57bd25a58f05dfa492d9b9c8ab62c5153satok Settings.Secure.getString(mContext.getContentResolver(), 186ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok Settings.Secure.SELECTED_SPELL_CHECKER); 187562ab585f9e413d9696ee250e5ec02f95889a157satok if (DBG) { 188562ab585f9e413d9696ee250e5ec02f95889a157satok Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId); 189562ab585f9e413d9696ee250e5ec02f95889a157satok } 190988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (TextUtils.isEmpty(curSpellCheckerId)) { 191df5659d3d317b5cf351baffe3e0d4876e89678bfsatok return null; 192988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 193988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return mSpellCheckerMap.get(curSpellCheckerId); 194988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 195988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 196988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 1973cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok // TODO: Respect allowImplicitlySelectedSubtype 198ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok // TODO: Save SpellCheckerSubtype by supported languages. 199ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok @Override 2003cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok public SpellCheckerSubtype getCurrentSpellCheckerSubtype( 2013cb5b39a0e63d98c4e7b47e9a5b5758e9d4024bdsatok String locale, boolean allowImplicitlySelectedSubtype) { 202ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok synchronized (mSpellCheckerMap) { 203ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok final String subtypeHashCodeStr = 204ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok Settings.Secure.getString(mContext.getContentResolver(), 205ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE); 206ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok if (DBG) { 207c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr); 208ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 209ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok final SpellCheckerInfo sci = getCurrentSpellChecker(null); 210a33c4fc5bed76727f1e06e522e0136101a2304cdsatok if (sci == null || sci.getSubtypeCount() == 0) { 211a33c4fc5bed76727f1e06e522e0136101a2304cdsatok if (DBG) { 212a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Slog.w(TAG, "Subtype not found."); 213a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 214ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok return null; 215ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 216b387954a92eb6f15b7f49d5b946745f492a26363satok final int hashCode; 217b387954a92eb6f15b7f49d5b946745f492a26363satok if (!TextUtils.isEmpty(subtypeHashCodeStr)) { 218b387954a92eb6f15b7f49d5b946745f492a26363satok hashCode = Integer.valueOf(subtypeHashCodeStr); 219b387954a92eb6f15b7f49d5b946745f492a26363satok } else { 220b387954a92eb6f15b7f49d5b946745f492a26363satok hashCode = 0; 221ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 222b387954a92eb6f15b7f49d5b946745f492a26363satok if (hashCode == 0 && !allowImplicitlySelectedSubtype) { 223fbedf1a3978d5dfc4a886e4c7107d4bc1923f740satok return null; 224fbedf1a3978d5dfc4a886e4c7107d4bc1923f740satok } 225b387954a92eb6f15b7f49d5b946745f492a26363satok final String systemLocale = 226b387954a92eb6f15b7f49d5b946745f492a26363satok mContext.getResources().getConfiguration().locale.toString(); 227b387954a92eb6f15b7f49d5b946745f492a26363satok SpellCheckerSubtype candidate = null; 228ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok for (int i = 0; i < sci.getSubtypeCount(); ++i) { 229ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok final SpellCheckerSubtype scs = sci.getSubtypeAt(i); 230b387954a92eb6f15b7f49d5b946745f492a26363satok if (hashCode == 0) { 231b387954a92eb6f15b7f49d5b946745f492a26363satok if (systemLocale.equals(locale)) { 232b387954a92eb6f15b7f49d5b946745f492a26363satok return scs; 233b387954a92eb6f15b7f49d5b946745f492a26363satok } else if (candidate == null) { 234b387954a92eb6f15b7f49d5b946745f492a26363satok final String scsLocale = scs.getLocale(); 235b387954a92eb6f15b7f49d5b946745f492a26363satok if (systemLocale.length() >= 2 236b387954a92eb6f15b7f49d5b946745f492a26363satok && scsLocale.length() >= 2 237b387954a92eb6f15b7f49d5b946745f492a26363satok && systemLocale.substring(0, 2).equals( 238b387954a92eb6f15b7f49d5b946745f492a26363satok scsLocale.substring(0, 2))) { 239b387954a92eb6f15b7f49d5b946745f492a26363satok candidate = scs; 240b387954a92eb6f15b7f49d5b946745f492a26363satok } 241b387954a92eb6f15b7f49d5b946745f492a26363satok } 242b387954a92eb6f15b7f49d5b946745f492a26363satok } else if (scs.hashCode() == hashCode) { 243a33c4fc5bed76727f1e06e522e0136101a2304cdsatok if (DBG) { 24470deff4c107963164f8b88365909fd30ab5e6526satok Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale 24570deff4c107963164f8b88365909fd30ab5e6526satok + ", " + scs.getLocale()); 246a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 247ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok return scs; 248ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 249ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 250b387954a92eb6f15b7f49d5b946745f492a26363satok return candidate; 251ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 252ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 253ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok 254988323c57bd25a58f05dfa492d9b9c8ab62c5153satok @Override 2555b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok public void getSpellCheckerService(String sciId, String locale, 2565357806980269d846a15c845a6fcc0384fb18860satok ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener, 2575357806980269d846a15c845a6fcc0384fb18860satok Bundle bundle) { 258988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (!mSystemReady) { 259988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return; 260988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 2615b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok if (TextUtils.isEmpty(sciId) || tsListener == null || scListener == null) { 262988323c57bd25a58f05dfa492d9b9c8ab62c5153satok Slog.e(TAG, "getSpellCheckerService: Invalid input."); 263988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return; 264988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 265988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized(mSpellCheckerMap) { 266988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (!mSpellCheckerMap.containsKey(sciId)) { 267988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return; 268988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 2695b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok final SpellCheckerInfo sci = mSpellCheckerMap.get(sciId); 270df5659d3d317b5cf351baffe3e0d4876e89678bfsatok final int uid = Binder.getCallingUid(); 271988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (mSpellCheckerBindGroups.containsKey(sciId)) { 2726be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId); 2736be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (bindGroup != null) { 2746be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final InternalDeathRecipient recipient = 2756be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok mSpellCheckerBindGroups.get(sciId).addListener( 2765357806980269d846a15c845a6fcc0384fb18860satok tsListener, locale, scListener, uid, bundle); 2776be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (recipient == null) { 2786be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (DBG) { 2796be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Slog.w(TAG, "Didn't create a death recipient."); 2806be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 2816be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok return; 2826be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 2836be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (bindGroup.mSpellChecker == null & bindGroup.mConnected) { 2846be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Slog.e(TAG, "The state of the spell checker bind group is illegal."); 2856be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok bindGroup.removeAll(); 2866be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } else if (bindGroup.mSpellChecker != null) { 2876be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (DBG) { 288df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Slog.w(TAG, "Existing bind found. Return a spell checker session now. " 289df5659d3d317b5cf351baffe3e0d4876e89678bfsatok + "Listeners count = " + bindGroup.mListeners.size()); 2906be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 2916be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok try { 2926be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final ISpellCheckerSession session = 2936be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok bindGroup.mSpellChecker.getISpellCheckerSession( 2945357806980269d846a15c845a6fcc0384fb18860satok recipient.mScLocale, recipient.mScListener, bundle); 295df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (session != null) { 296df5659d3d317b5cf351baffe3e0d4876e89678bfsatok tsListener.onServiceConnected(session); 297df5659d3d317b5cf351baffe3e0d4876e89678bfsatok return; 298df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } else { 299df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (DBG) { 300df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Slog.w(TAG, "Existing bind already expired. "); 301df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 302df5659d3d317b5cf351baffe3e0d4876e89678bfsatok bindGroup.removeAll(); 303df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 3046be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } catch (RemoteException e) { 3056be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Slog.e(TAG, "Exception in getting spell checker session: " + e); 3066be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok bindGroup.removeAll(); 3076be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 3086be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 3096be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 310988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 3116be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final long ident = Binder.clearCallingIdentity(); 3126be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok try { 3135357806980269d846a15c845a6fcc0384fb18860satok startSpellCheckerServiceInnerLocked( 3145357806980269d846a15c845a6fcc0384fb18860satok sci, locale, tsListener, scListener, uid, bundle); 3156be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } finally { 3166be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Binder.restoreCallingIdentity(ident); 317988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 318988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 319988323c57bd25a58f05dfa492d9b9c8ab62c5153satok return; 320988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 321988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 322a33c4fc5bed76727f1e06e522e0136101a2304cdsatok @Override 323a33c4fc5bed76727f1e06e522e0136101a2304cdsatok public boolean isSpellCheckerEnabled() { 324a33c4fc5bed76727f1e06e522e0136101a2304cdsatok synchronized(mSpellCheckerMap) { 325a33c4fc5bed76727f1e06e522e0136101a2304cdsatok return isSpellCheckerEnabledLocked(); 326a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 327a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 328a33c4fc5bed76727f1e06e522e0136101a2304cdsatok 3296be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale, 330df5659d3d317b5cf351baffe3e0d4876e89678bfsatok ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener, 3315357806980269d846a15c845a6fcc0384fb18860satok int uid, Bundle bundle) { 332df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (DBG) { 333df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Slog.w(TAG, "Start spell checker session inner locked."); 334df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 3356be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final String sciId = info.getId(); 3366be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final InternalServiceConnection connection = new InternalServiceConnection( 3375357806980269d846a15c845a6fcc0384fb18860satok sciId, locale, scListener, bundle); 3386be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); 3396be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok serviceIntent.setComponent(info.getComponent()); 3406be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (DBG) { 3416be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Slog.w(TAG, "bind service: " + info.getId()); 3426be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 3436be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { 3446be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Slog.e(TAG, "Failed to get a spell checker service."); 3456be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok return; 3466be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 3476be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok final SpellCheckerBindGroup group = new SpellCheckerBindGroup( 3485357806980269d846a15c845a6fcc0384fb18860satok connection, tsListener, locale, scListener, uid, bundle); 3496be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok mSpellCheckerBindGroups.put(sciId, group); 3506be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 3516be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok 352988323c57bd25a58f05dfa492d9b9c8ab62c5153satok @Override 353562ab585f9e413d9696ee250e5ec02f95889a157satok public SpellCheckerInfo[] getEnabledSpellCheckers() { 354da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 355da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "getEnabledSpellCheckers: " + mSpellCheckerList.size()); 356da317ef68603dc7649f98bda495267973825e7fasatok for (int i = 0; i < mSpellCheckerList.size(); ++i) { 357da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "EnabledSpellCheckers: " + mSpellCheckerList.get(i).getPackageName()); 358da317ef68603dc7649f98bda495267973825e7fasatok } 359da317ef68603dc7649f98bda495267973825e7fasatok } 360562ab585f9e413d9696ee250e5ec02f95889a157satok return mSpellCheckerList.toArray(new SpellCheckerInfo[mSpellCheckerList.size()]); 361562ab585f9e413d9696ee250e5ec02f95889a157satok } 362562ab585f9e413d9696ee250e5ec02f95889a157satok 363562ab585f9e413d9696ee250e5ec02f95889a157satok @Override 364988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void finishSpellCheckerService(ISpellCheckerSessionListener listener) { 365da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 366da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "FinishSpellCheckerService"); 367da317ef68603dc7649f98bda495267973825e7fasatok } 368988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized(mSpellCheckerMap) { 369988323c57bd25a58f05dfa492d9b9c8ab62c5153satok for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) { 370988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (group == null) continue; 371988323c57bd25a58f05dfa492d9b9c8ab62c5153satok group.removeListener(listener); 372988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 373988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 374988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 375988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 376df5659d3d317b5cf351baffe3e0d4876e89678bfsatok @Override 377ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok public void setCurrentSpellChecker(String locale, String sciId) { 378df5659d3d317b5cf351baffe3e0d4876e89678bfsatok synchronized(mSpellCheckerMap) { 379df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (mContext.checkCallingOrSelfPermission( 380df5659d3d317b5cf351baffe3e0d4876e89678bfsatok android.Manifest.permission.WRITE_SECURE_SETTINGS) 381df5659d3d317b5cf351baffe3e0d4876e89678bfsatok != PackageManager.PERMISSION_GRANTED) { 382df5659d3d317b5cf351baffe3e0d4876e89678bfsatok throw new SecurityException( 383df5659d3d317b5cf351baffe3e0d4876e89678bfsatok "Requires permission " 384df5659d3d317b5cf351baffe3e0d4876e89678bfsatok + android.Manifest.permission.WRITE_SECURE_SETTINGS); 385df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 3865b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok setCurrentSpellCheckerLocked(sciId); 387df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 388df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 389df5659d3d317b5cf351baffe3e0d4876e89678bfsatok 390ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok @Override 391ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok public void setCurrentSpellCheckerSubtype(String locale, int hashCode) { 392ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok synchronized(mSpellCheckerMap) { 393ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok if (mContext.checkCallingOrSelfPermission( 394ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok android.Manifest.permission.WRITE_SECURE_SETTINGS) 395ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok != PackageManager.PERMISSION_GRANTED) { 396ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok throw new SecurityException( 397ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok "Requires permission " 398ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok + android.Manifest.permission.WRITE_SECURE_SETTINGS); 399ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 400a33c4fc5bed76727f1e06e522e0136101a2304cdsatok setCurrentSpellCheckerSubtypeLocked(hashCode); 401a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 402a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 403a33c4fc5bed76727f1e06e522e0136101a2304cdsatok 404a33c4fc5bed76727f1e06e522e0136101a2304cdsatok @Override 405a33c4fc5bed76727f1e06e522e0136101a2304cdsatok public void setSpellCheckerEnabled(boolean enabled) { 406a33c4fc5bed76727f1e06e522e0136101a2304cdsatok synchronized(mSpellCheckerMap) { 407a33c4fc5bed76727f1e06e522e0136101a2304cdsatok if (mContext.checkCallingOrSelfPermission( 408a33c4fc5bed76727f1e06e522e0136101a2304cdsatok android.Manifest.permission.WRITE_SECURE_SETTINGS) 409a33c4fc5bed76727f1e06e522e0136101a2304cdsatok != PackageManager.PERMISSION_GRANTED) { 410a33c4fc5bed76727f1e06e522e0136101a2304cdsatok throw new SecurityException( 411a33c4fc5bed76727f1e06e522e0136101a2304cdsatok "Requires permission " 412a33c4fc5bed76727f1e06e522e0136101a2304cdsatok + android.Manifest.permission.WRITE_SECURE_SETTINGS); 413a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 414a33c4fc5bed76727f1e06e522e0136101a2304cdsatok setSpellCheckerEnabledLocked(enabled); 415ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 416ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 417ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok 4185b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok private void setCurrentSpellCheckerLocked(String sciId) { 419562ab585f9e413d9696ee250e5ec02f95889a157satok if (DBG) { 4205b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok Slog.w(TAG, "setCurrentSpellChecker: " + sciId); 421562ab585f9e413d9696ee250e5ec02f95889a157satok } 4225b9b5a9553a0276dc6b7f1f458c8d4ed03227988satok if (TextUtils.isEmpty(sciId) || !mSpellCheckerMap.containsKey(sciId)) return; 423f39daef102f2dff7517e257eb25c2e3677247e83satok final SpellCheckerInfo currentSci = getCurrentSpellChecker(null); 424f39daef102f2dff7517e257eb25c2e3677247e83satok if (currentSci != null && currentSci.getId().equals(sciId)) { 425f39daef102f2dff7517e257eb25c2e3677247e83satok // Do nothing if the current spell checker is same as new spell checker. 426f39daef102f2dff7517e257eb25c2e3677247e83satok return; 427f39daef102f2dff7517e257eb25c2e3677247e83satok } 428df5659d3d317b5cf351baffe3e0d4876e89678bfsatok final long ident = Binder.clearCallingIdentity(); 429df5659d3d317b5cf351baffe3e0d4876e89678bfsatok try { 430df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Settings.Secure.putString(mContext.getContentResolver(), 431ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok Settings.Secure.SELECTED_SPELL_CHECKER, sciId); 432f39daef102f2dff7517e257eb25c2e3677247e83satok setCurrentSpellCheckerSubtypeLocked(0); 433ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } finally { 434ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok Binder.restoreCallingIdentity(ident); 435ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 436ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 437ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok 438a33c4fc5bed76727f1e06e522e0136101a2304cdsatok private void setCurrentSpellCheckerSubtypeLocked(int hashCode) { 439ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok if (DBG) { 440ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok Slog.w(TAG, "setCurrentSpellCheckerSubtype: " + hashCode); 441ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 442ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok final SpellCheckerInfo sci = getCurrentSpellChecker(null); 443fbedf1a3978d5dfc4a886e4c7107d4bc1923f740satok int tempHashCode = 0; 444fbedf1a3978d5dfc4a886e4c7107d4bc1923f740satok for (int i = 0; sci != null && i < sci.getSubtypeCount(); ++i) { 445ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok if(sci.getSubtypeAt(i).hashCode() == hashCode) { 446fbedf1a3978d5dfc4a886e4c7107d4bc1923f740satok tempHashCode = hashCode; 447ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok break; 448ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 449ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok } 450ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok final long ident = Binder.clearCallingIdentity(); 451ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok try { 452ada8c4e6a3da96a795f39a1028d448eb7aebfab3satok Settings.Secure.putString(mContext.getContentResolver(), 453fbedf1a3978d5dfc4a886e4c7107d4bc1923f740satok Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(tempHashCode)); 454df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } finally { 455df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Binder.restoreCallingIdentity(ident); 456df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 457988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 458988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 459a33c4fc5bed76727f1e06e522e0136101a2304cdsatok private void setSpellCheckerEnabledLocked(boolean enabled) { 460a33c4fc5bed76727f1e06e522e0136101a2304cdsatok if (DBG) { 461a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Slog.w(TAG, "setSpellCheckerEnabled: " + enabled); 462a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 463a33c4fc5bed76727f1e06e522e0136101a2304cdsatok final long ident = Binder.clearCallingIdentity(); 464a33c4fc5bed76727f1e06e522e0136101a2304cdsatok try { 465a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Settings.Secure.putInt(mContext.getContentResolver(), 466a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Settings.Secure.SPELL_CHECKER_ENABLED, enabled ? 1 : 0); 467a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } finally { 468a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Binder.restoreCallingIdentity(ident); 469a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 470a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 471a33c4fc5bed76727f1e06e522e0136101a2304cdsatok 472a33c4fc5bed76727f1e06e522e0136101a2304cdsatok private boolean isSpellCheckerEnabledLocked() { 473a33c4fc5bed76727f1e06e522e0136101a2304cdsatok final long ident = Binder.clearCallingIdentity(); 474a33c4fc5bed76727f1e06e522e0136101a2304cdsatok try { 475a33c4fc5bed76727f1e06e522e0136101a2304cdsatok final boolean retval = Settings.Secure.getInt(mContext.getContentResolver(), 476a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Settings.Secure.SPELL_CHECKER_ENABLED, 1) == 1; 477a33c4fc5bed76727f1e06e522e0136101a2304cdsatok if (DBG) { 478a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Slog.w(TAG, "getSpellCheckerEnabled: " + retval); 479a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 480a33c4fc5bed76727f1e06e522e0136101a2304cdsatok return retval; 481a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } finally { 482a33c4fc5bed76727f1e06e522e0136101a2304cdsatok Binder.restoreCallingIdentity(ident); 483a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 484a33c4fc5bed76727f1e06e522e0136101a2304cdsatok } 485a33c4fc5bed76727f1e06e522e0136101a2304cdsatok 48671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn @Override 48771e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 48871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 48971e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn != PackageManager.PERMISSION_GRANTED) { 49071e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn 49171e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println("Permission Denial: can't dump TextServicesManagerService from from pid=" 49271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn + Binder.getCallingPid() 49371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn + ", uid=" + Binder.getCallingUid()); 49471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn return; 49571e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 49671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn 49771e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn synchronized(mSpellCheckerMap) { 49871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println("Current Text Services Manager state:"); 49971e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(" Spell Checker Map:"); 50071e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn for (Map.Entry<String, SpellCheckerInfo> ent : mSpellCheckerMap.entrySet()) { 50171e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 50271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn SpellCheckerInfo info = ent.getValue(); 50371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("id="); pw.println(info.getId()); 50471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("comp="); 50571e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(info.getComponent().toShortString()); 50671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn int NS = info.getSubtypeCount(); 50771e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn for (int i=0; i<NS; i++) { 50871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn SpellCheckerSubtype st = info.getSubtypeAt(i); 50971e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("Subtype #"); pw.print(i); pw.println(":"); 51071e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("locale="); pw.println(st.getLocale()); 51171e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("extraValue="); 51271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(st.getExtraValue()); 51371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 51471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 51571e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(""); 51671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(" Spell Checker Bind Groups:"); 51771e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn for (Map.Entry<String, SpellCheckerBindGroup> ent 51871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn : mSpellCheckerBindGroups.entrySet()) { 51971e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn SpellCheckerBindGroup grp = ent.getValue(); 52071e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print(ent.getKey()); pw.print(" "); 52171e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(grp); pw.println(":"); 52271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("mInternalConnection="); 52371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(grp.mInternalConnection); 52471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("mSpellChecker="); 52571e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(grp.mSpellChecker); 52671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("mBound="); pw.print(grp.mBound); 52771e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" mConnected="); pw.println(grp.mConnected); 52871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn int NL = grp.mListeners.size(); 52971e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn for (int i=0; i<NL; i++) { 53071e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn InternalDeathRecipient listener = grp.mListeners.get(i); 53171e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("Listener #"); pw.print(i); pw.println(":"); 53271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("mTsListener="); 53371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(listener.mTsListener); 53471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("mScListener="); 53571e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(listener.mScListener); 53671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("mGroup="); 53771e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.println(listener.mGroup); 53871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" "); pw.print("mScLocale="); 53971e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(listener.mScLocale); 54071e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn pw.print(" mUid="); pw.println(listener.mUid); 54171e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 54271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 54371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 54471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 54571e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn 546988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // SpellCheckerBindGroup contains active text service session listeners. 547988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from 548988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // mSpellCheckerBindGroups 549988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private class SpellCheckerBindGroup { 550df5659d3d317b5cf351baffe3e0d4876e89678bfsatok private final String TAG = SpellCheckerBindGroup.class.getSimpleName(); 5516be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok private final InternalServiceConnection mInternalConnection; 5526be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok private final ArrayList<InternalDeathRecipient> mListeners = 553988323c57bd25a58f05dfa492d9b9c8ab62c5153satok new ArrayList<InternalDeathRecipient>(); 55471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn public boolean mBound; 5556be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok public ISpellCheckerService mSpellChecker; 5566be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok public boolean mConnected; 557988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 558988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public SpellCheckerBindGroup(InternalServiceConnection connection, 559988323c57bd25a58f05dfa492d9b9c8ab62c5153satok ITextServicesSessionListener listener, String locale, 5605357806980269d846a15c845a6fcc0384fb18860satok ISpellCheckerSessionListener scListener, int uid, Bundle bundle) { 561988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mInternalConnection = connection; 56271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn mBound = true; 5636be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok mConnected = false; 5645357806980269d846a15c845a6fcc0384fb18860satok addListener(listener, locale, scListener, uid, bundle); 565988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 566988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 567988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void onServiceConnected(ISpellCheckerService spellChecker) { 568da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 569da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "onServiceConnected"); 570da317ef68603dc7649f98bda495267973825e7fasatok } 571988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized(mSpellCheckerMap) { 572988323c57bd25a58f05dfa492d9b9c8ab62c5153satok for (InternalDeathRecipient listener : mListeners) { 573988323c57bd25a58f05dfa492d9b9c8ab62c5153satok try { 574988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final ISpellCheckerSession session = spellChecker.getISpellCheckerSession( 5755357806980269d846a15c845a6fcc0384fb18860satok listener.mScLocale, listener.mScListener, listener.mBundle); 576988323c57bd25a58f05dfa492d9b9c8ab62c5153satok listener.mTsListener.onServiceConnected(session); 577988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } catch (RemoteException e) { 578c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok Slog.e(TAG, "Exception in getting the spell checker session." 579c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok + "Reconnect to the spellchecker. ", e); 5806be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok removeAll(); 5816be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok return; 582988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 583988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 5846be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok mSpellChecker = spellChecker; 5856be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok mConnected = true; 586988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 587988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 588988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 5896be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener, 5905357806980269d846a15c845a6fcc0384fb18860satok String locale, ISpellCheckerSessionListener scListener, int uid, Bundle bundle) { 591da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 592da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "addListener: " + locale); 593da317ef68603dc7649f98bda495267973825e7fasatok } 5946be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok InternalDeathRecipient recipient = null; 595988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized(mSpellCheckerMap) { 596988323c57bd25a58f05dfa492d9b9c8ab62c5153satok try { 597988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final int size = mListeners.size(); 598988323c57bd25a58f05dfa492d9b9c8ab62c5153satok for (int i = 0; i < size; ++i) { 599988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if (mListeners.get(i).hasSpellCheckerListener(scListener)) { 600988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // do not add the lister if the group already contains this. 6016be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok return null; 602988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 603988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 6046be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok recipient = new InternalDeathRecipient( 6055357806980269d846a15c845a6fcc0384fb18860satok this, tsListener, locale, scListener, uid, bundle); 606988323c57bd25a58f05dfa492d9b9c8ab62c5153satok scListener.asBinder().linkToDeath(recipient, 0); 607df5659d3d317b5cf351baffe3e0d4876e89678bfsatok mListeners.add(recipient); 608988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } catch(RemoteException e) { 609988323c57bd25a58f05dfa492d9b9c8ab62c5153satok // do nothing 610988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 611988323c57bd25a58f05dfa492d9b9c8ab62c5153satok cleanLocked(); 612988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 6136be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok return recipient; 614988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 615988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 616988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void removeListener(ISpellCheckerSessionListener listener) { 617da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 618df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Slog.w(TAG, "remove listener: " + listener.hashCode()); 619da317ef68603dc7649f98bda495267973825e7fasatok } 620988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized(mSpellCheckerMap) { 621988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final int size = mListeners.size(); 622988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final ArrayList<InternalDeathRecipient> removeList = 623988323c57bd25a58f05dfa492d9b9c8ab62c5153satok new ArrayList<InternalDeathRecipient>(); 624988323c57bd25a58f05dfa492d9b9c8ab62c5153satok for (int i = 0; i < size; ++i) { 625988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final InternalDeathRecipient tempRecipient = mListeners.get(i); 626988323c57bd25a58f05dfa492d9b9c8ab62c5153satok if(tempRecipient.hasSpellCheckerListener(listener)) { 627df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (DBG) { 628df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Slog.w(TAG, "found existing listener."); 629df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 630988323c57bd25a58f05dfa492d9b9c8ab62c5153satok removeList.add(tempRecipient); 631988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 632988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 633988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final int removeSize = removeList.size(); 634988323c57bd25a58f05dfa492d9b9c8ab62c5153satok for (int i = 0; i < removeSize; ++i) { 635df5659d3d317b5cf351baffe3e0d4876e89678bfsatok if (DBG) { 636df5659d3d317b5cf351baffe3e0d4876e89678bfsatok Slog.w(TAG, "Remove " + removeList.get(i)); 637df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 638988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mListeners.remove(removeList.get(i)); 639988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 640988323c57bd25a58f05dfa492d9b9c8ab62c5153satok cleanLocked(); 641988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 642988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 643988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 644988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private void cleanLocked() { 645da317ef68603dc7649f98bda495267973825e7fasatok if (DBG) { 646da317ef68603dc7649f98bda495267973825e7fasatok Slog.d(TAG, "cleanLocked"); 647da317ef68603dc7649f98bda495267973825e7fasatok } 64871e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn // If there are no more active listeners, clean up. Only do this 64971e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn // once. 65071e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn if (mBound && mListeners.isEmpty()) { 65171e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn mBound = false; 652c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok final String sciId = mInternalConnection.mSciId; 65371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn SpellCheckerBindGroup cur = mSpellCheckerBindGroups.get(sciId); 65471e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn if (cur == this) { 655c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok if (DBG) { 656c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok Slog.d(TAG, "Remove bind group."); 657c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok } 658c7b60f72dda5c5f222342a9d60435ec353a8a19bsatok mSpellCheckerBindGroups.remove(sciId); 6596be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 660988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mContext.unbindService(mInternalConnection); 661988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 662988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 6636be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok 6646be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok public void removeAll() { 6656be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Slog.e(TAG, "Remove the spell checker bind unexpectedly."); 666df5659d3d317b5cf351baffe3e0d4876e89678bfsatok synchronized(mSpellCheckerMap) { 667df5659d3d317b5cf351baffe3e0d4876e89678bfsatok mListeners.clear(); 668df5659d3d317b5cf351baffe3e0d4876e89678bfsatok cleanLocked(); 669df5659d3d317b5cf351baffe3e0d4876e89678bfsatok } 6706be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 671988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 672988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 673988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private class InternalServiceConnection implements ServiceConnection { 674988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final ISpellCheckerSessionListener mListener; 675988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final String mSciId; 676988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final String mLocale; 6775357806980269d846a15c845a6fcc0384fb18860satok private final Bundle mBundle; 678988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public InternalServiceConnection( 6795357806980269d846a15c845a6fcc0384fb18860satok String id, String locale, ISpellCheckerSessionListener listener, Bundle bundle) { 680988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mSciId = id; 681988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mLocale = locale; 682988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mListener = listener; 6835357806980269d846a15c845a6fcc0384fb18860satok mBundle = bundle; 684988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 685988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 686988323c57bd25a58f05dfa492d9b9c8ab62c5153satok @Override 687988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void onServiceConnected(ComponentName name, IBinder service) { 688988323c57bd25a58f05dfa492d9b9c8ab62c5153satok synchronized(mSpellCheckerMap) { 6896be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok if (DBG) { 6906be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok Slog.w(TAG, "onServiceConnected: " + name); 6916be6d7548fb7c29a4d46dc985318ab2adf69f95fsatok } 692988323c57bd25a58f05dfa492d9b9c8ab62c5153satok ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); 693988323c57bd25a58f05dfa492d9b9c8ab62c5153satok final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); 694c7d233d93f84fce9877c3eb645bbb515baf0dc0aDianne Hackborn if (group != null && this == group.mInternalConnection) { 695988323c57bd25a58f05dfa492d9b9c8ab62c5153satok group.onServiceConnected(spellChecker); 696988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 697988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 698988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 699988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 700988323c57bd25a58f05dfa492d9b9c8ab62c5153satok @Override 701988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void onServiceDisconnected(ComponentName name) { 70271e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn synchronized(mSpellCheckerMap) { 70371e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); 7042cf1cf098513807ffd3420ae106f438e943d0cd8satok if (group != null && this == group.mInternalConnection) { 70571e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn mSpellCheckerBindGroups.remove(mSciId); 70671e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 70771e14da93c8fea512fedf1b5226d28cd2c330238Dianne Hackborn } 708988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 709988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 710988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 711988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private class InternalDeathRecipient implements IBinder.DeathRecipient { 712988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public final ITextServicesSessionListener mTsListener; 713988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public final ISpellCheckerSessionListener mScListener; 714988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public final String mScLocale; 715988323c57bd25a58f05dfa492d9b9c8ab62c5153satok private final SpellCheckerBindGroup mGroup; 716df5659d3d317b5cf351baffe3e0d4876e89678bfsatok public final int mUid; 7175357806980269d846a15c845a6fcc0384fb18860satok public final Bundle mBundle; 718988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public InternalDeathRecipient(SpellCheckerBindGroup group, 719988323c57bd25a58f05dfa492d9b9c8ab62c5153satok ITextServicesSessionListener tsListener, String scLocale, 7205357806980269d846a15c845a6fcc0384fb18860satok ISpellCheckerSessionListener scListener, int uid, Bundle bundle) { 721988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mTsListener = tsListener; 722988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mScListener = scListener; 723988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mScLocale = scLocale; 724988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mGroup = group; 725df5659d3d317b5cf351baffe3e0d4876e89678bfsatok mUid = uid; 7265357806980269d846a15c845a6fcc0384fb18860satok mBundle = bundle; 727988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 728988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 729988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) { 730df5659d3d317b5cf351baffe3e0d4876e89678bfsatok return listener.asBinder().equals(mScListener.asBinder()); 731988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 732988323c57bd25a58f05dfa492d9b9c8ab62c5153satok 733988323c57bd25a58f05dfa492d9b9c8ab62c5153satok @Override 734988323c57bd25a58f05dfa492d9b9c8ab62c5153satok public void binderDied() { 735988323c57bd25a58f05dfa492d9b9c8ab62c5153satok mGroup.removeListener(mScListener); 736988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 737988323c57bd25a58f05dfa492d9b9c8ab62c5153satok } 738988323c57bd25a58f05dfa492d9b9c8ab62c5153satok} 739