diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/nfc/NdefTagConnection.java | 16 | ||||
| -rw-r--r-- | core/java/android/nfc/NfcAdapter.java | 62 | ||||
| -rw-r--r-- | core/java/android/nfc/RawTagConnection.java | 39 | ||||
| -rw-r--r-- | core/java/android/preference/PreferenceFragment.java | 2 | ||||
| -rw-r--r-- | core/java/android/provider/Settings.java | 14 | ||||
| -rw-r--r-- | core/java/android/webkit/BrowserFrame.java | 33 | ||||
| -rw-r--r-- | core/java/android/webkit/CookieSyncManager.java | 42 | ||||
| -rw-r--r-- | core/java/android/webkit/WebView.java | 2 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewCore.java | 6 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java | 319 |
10 files changed, 145 insertions, 390 deletions
diff --git a/core/java/android/nfc/NdefTagConnection.java b/core/java/android/nfc/NdefTagConnection.java index 321b0ec..27fa25c 100644 --- a/core/java/android/nfc/NdefTagConnection.java +++ b/core/java/android/nfc/NdefTagConnection.java @@ -42,8 +42,8 @@ public class NdefTagConnection extends RawTagConnection { * Internal constructor, to be used by NfcAdapter * @hide */ - /* package private */ NdefTagConnection(INfcAdapter service, NdefTag tag, String target) throws RemoteException { - super(service, tag); + /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag, String target) throws RemoteException { + super(adapter, tag); String[] targets = tag.getNdefTargets(); int i; @@ -63,8 +63,8 @@ public class NdefTagConnection extends RawTagConnection { * Internal constructor, to be used by NfcAdapter * @hide */ - /* package private */ NdefTagConnection(INfcAdapter service, NdefTag tag) throws RemoteException { - this(service, tag, tag.getNdefTargets()[0]); + /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag) throws RemoteException { + this(adapter, tag, tag.getNdefTargets()[0]); } /** @@ -97,7 +97,7 @@ public class NdefTagConnection extends RawTagConnection { msgArray[0] = msg; return msgArray; } catch (RemoteException e) { - Log.e(TAG, "NFC service died"); + attemptDeadServiceRecovery(e); return null; } } @@ -134,7 +134,7 @@ public class NdefTagConnection extends RawTagConnection { throw new IOException(); } } catch (RemoteException e) { - Log.e(TAG, "NFC service died"); + attemptDeadServiceRecovery(e); } } @@ -161,7 +161,7 @@ public class NdefTagConnection extends RawTagConnection { throw new IOException(); } } catch (RemoteException e) { - Log.e(TAG, "NFC service died"); + attemptDeadServiceRecovery(e); return false; } } @@ -188,7 +188,7 @@ public class NdefTagConnection extends RawTagConnection { return result; } catch (RemoteException e) { - Log.e(TAG, "NFC service died"); + attemptDeadServiceRecovery(e); return NDEF_MODE_UNKNOWN; } } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 7f4b4a2..a093d12 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -168,7 +168,10 @@ public final class NfcAdapter { private static boolean sIsInitialized = false; private static NfcAdapter sAdapter; - private final INfcAdapter mService; + // Final after construction, except for attemptDeadServiceRecovery() + // when NFC crashes. + // Not locked - we accept a best effort attempt when NFC crashes. + /*package*/ INfcAdapter mService; private NfcAdapter(INfcAdapter service) { mService = service; @@ -194,6 +197,16 @@ public final class NfcAdapter { } } + /** get handle to NFC service interface */ + private static synchronized INfcAdapter getServiceInterface() { + /* get a handle to NFC service */ + IBinder b = ServiceManager.getService("nfc"); + if (b == null) { + return null; + } + return INfcAdapter.Stub.asInterface(b); + } + /** * Get a handle to the default NFC Adapter on this Android device. * <p> @@ -214,18 +227,31 @@ public final class NfcAdapter { return null; } - /* get a handle to NFC service */ - IBinder b = ServiceManager.getService("nfc"); - if (b == null) { + INfcAdapter service = getServiceInterface(); + if (service == null) { Log.e(TAG, "could not retrieve NFC service"); return null; } - sAdapter = new NfcAdapter(INfcAdapter.Stub.asInterface(b)); + sAdapter = new NfcAdapter(service); return sAdapter; } } + /** NFC service dead - attempt best effort recovery */ + /*package*/ void attemptDeadServiceRecovery(Exception e) { + Log.e(TAG, "NFC service dead - attempting to recover", e); + INfcAdapter service = getServiceInterface(); + if (service == null) { + Log.e(TAG, "could not retrieve NFC service during service recovery"); + return; + } + /* assigning to mService is not thread-safe, but this is best-effort code + * and on a well-behaved system should never happen */ + mService = service; + return; + } + /** * Return true if this NFC Adapter has any features enabled. * <p> @@ -241,7 +267,7 @@ public final class NfcAdapter { try { return mService.isEnabled(); } catch (RemoteException e) { - Log.e(TAG, "RemoteException in isEnabled()", e); + attemptDeadServiceRecovery(e); return false; } } @@ -258,7 +284,7 @@ public final class NfcAdapter { try { return mService.enable(); } catch (RemoteException e) { - Log.e(TAG, "RemoteException in enable()", e); + attemptDeadServiceRecovery(e); return false; } } @@ -277,7 +303,7 @@ public final class NfcAdapter { try { return mService.disable(); } catch (RemoteException e) { - Log.e(TAG, "RemoteException in disable()", e); + attemptDeadServiceRecovery(e); return false; } } @@ -303,7 +329,7 @@ public final class NfcAdapter { try { mService.localSet(message); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); } } @@ -317,7 +343,7 @@ public final class NfcAdapter { try { return mService.localGet(); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); return null; } } @@ -331,9 +357,9 @@ public final class NfcAdapter { throw new IllegalArgumentException("mock tag cannot be used for connections"); } try { - return new RawTagConnection(mService, tag); + return new RawTagConnection(this, tag); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); return null; } } @@ -347,9 +373,9 @@ public final class NfcAdapter { throw new IllegalArgumentException("mock tag cannot be used for connections"); } try { - return new RawTagConnection(mService, tag, target); + return new RawTagConnection(this, tag, target); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); return null; } } @@ -363,9 +389,9 @@ public final class NfcAdapter { throw new IllegalArgumentException("mock tag cannot be used for connections"); } try { - return new NdefTagConnection(mService, tag); + return new NdefTagConnection(this, tag); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); return null; } } @@ -379,9 +405,9 @@ public final class NfcAdapter { throw new IllegalArgumentException("mock tag cannot be used for connections"); } try { - return new NdefTagConnection(mService, tag, target); + return new NdefTagConnection(this, tag, target); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); return null; } } diff --git a/core/java/android/nfc/RawTagConnection.java b/core/java/android/nfc/RawTagConnection.java index 8442893..24072e5 100644 --- a/core/java/android/nfc/RawTagConnection.java +++ b/core/java/android/nfc/RawTagConnection.java @@ -35,15 +35,20 @@ import android.util.Log; */ public class RawTagConnection { - /*package*/ final INfcAdapter mService; - /*package*/ final INfcTag mTagService; /*package*/ final Tag mTag; /*package*/ boolean mIsConnected; /*package*/ String mSelectedTarget; + private final NfcAdapter mAdapter; + + // Following fields are final after construction, except for + // during attemptDeadServiceRecovery() when NFC crashes. + // Not locked - we accept a best effort attempt when NFC crashes. + /*package*/ INfcAdapter mService; + /*package*/ INfcTag mTagService; private static final String TAG = "NFC"; - /* package private */ RawTagConnection(INfcAdapter service, Tag tag, String target) throws RemoteException { + /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag, String target) throws RemoteException { String[] targets = tag.getRawTargets(); int i; @@ -58,14 +63,28 @@ public class RawTagConnection { throw new IllegalArgumentException(); } - mService = service; - mTagService = service.getNfcTagInterface(); + mAdapter = adapter; + mService = mAdapter.mService; + mTagService = mService.getNfcTagInterface(); mTag = tag; mSelectedTarget = target; } - /* package private */ RawTagConnection(INfcAdapter service, Tag tag) throws RemoteException { - this(service, tag, tag.getRawTargets()[0]); + /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag) throws RemoteException { + this(adapter, tag, tag.getRawTargets()[0]); + } + + /** NFC service dead - attempt best effort recovery */ + /*package*/ void attemptDeadServiceRecovery(Exception e) { + mAdapter.attemptDeadServiceRecovery(e); + /* assigning to mService is not thread-safe, but this is best-effort code + * and on a well-behaved system should never happen */ + mService = mAdapter.mService; + try { + mTagService = mService.getNfcTagInterface(); + } catch (RemoteException e2) { + Log.e(TAG, "second RemoteException trying to recover from dead NFC service", e2); + } } /** @@ -101,7 +120,7 @@ public class RawTagConnection { try { return mTagService.isPresent(mTag.mServiceHandle); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); return false; } } @@ -136,7 +155,7 @@ public class RawTagConnection { try { mTagService.close(mTag.mServiceHandle); } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); } } @@ -159,7 +178,7 @@ public class RawTagConnection { } return response; } catch (RemoteException e) { - Log.e(TAG, "NFC service died", e); + attemptDeadServiceRecovery(e); throw new IOException("NFC service died"); } } diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java index 7629c31..33f37f8 100644 --- a/core/java/android/preference/PreferenceFragment.java +++ b/core/java/android/preference/PreferenceFragment.java @@ -151,7 +151,7 @@ public abstract class PreferenceFragment extends Fragment implements @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(com.android.internal.R.layout.preference_list_content, + return inflater.inflate(com.android.internal.R.layout.preference_list_fragment, container, false); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 62d2ff2..2b79037 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -279,6 +279,20 @@ public final class Settings { "android.settings.INPUT_METHOD_SETTINGS"; /** + * Activity Action: Show enabler activity to enable/disable input methods and subtypes. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_INPUT_METHOD_AND_SUBTYPE_ENABLER = + "android.settings.INPUT_METHOD_AND_SUBTYPE_ENABLER"; + + /** * Activity Action: Show settings to manage the user input dictionary. * <p> * In some cases, a matching Activity may not exist, so ensure you diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index 6e588b9..2087664 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -74,8 +74,6 @@ class BrowserFrame extends Handler { // queue has been cleared,they are ignored. private boolean mBlockMessages = false; private int mOrientation = -1; - private static String sDatabaseDirectory; - private static String sCacheDirectory; // Is this frame the main frame? private boolean mIsMainFrame; @@ -229,13 +227,6 @@ class BrowserFrame extends Handler { AssetManager am = context.getAssets(); nativeCreateFrame(w, am, proxy.getBackForwardList()); - if (sDatabaseDirectory == null) { - sDatabaseDirectory = appContext.getDatabasePath("dummy").getParent(); - } - if (sCacheDirectory == null) { - sCacheDirectory = appContext.getCacheDir().getAbsolutePath(); - } - if (DebugFlags.BROWSER_FRAME) { Log.v(LOGTAG, "BrowserFrame constructor: this=" + this); } @@ -658,22 +649,6 @@ class BrowserFrame extends Handler { } /** - * Called by JNI. Gets the application's database directory, excluding the trailing slash. - * @return String The application's database directory - */ - private static String getDatabaseDirectory() { - return sDatabaseDirectory; - } - - /** - * Called by JNI. Gets the application's cache directory, excluding the trailing slash. - * @return String The application's cache directory - */ - private static String getCacheDirectory() { - return sCacheDirectory; - } - - /** * Called by JNI. * Read from an InputStream into a supplied byte[] * This method catches any exceptions so they don't crash the JVM. @@ -752,6 +727,14 @@ class BrowserFrame extends Handler { } } else if (type == CONTENT) { try { + // Strip off mimetype, for compatibility with ContentLoader.java + // If we don't do this, we can fail to load Gmail attachments, + // because the URL being loaded doesn't exactly match the URL we + // have permission to read. + int mimeIndex = url.lastIndexOf('?'); + if (mimeIndex != -1) { + url = url.substring(0, mimeIndex); + } Uri uri = Uri.parse(url); return mContext.getContentResolver().openInputStream(uri); } catch (Exception e) { diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java index abe9178..8b76a3b 100644 --- a/core/java/android/webkit/CookieSyncManager.java +++ b/core/java/android/webkit/CookieSyncManager.java @@ -65,6 +65,11 @@ public final class CookieSyncManager extends WebSyncManager { // time when last update happened private long mLastUpdate; + // Used by the Chromium HTTP stack. Everything else in this class is used only by the Android + // Java HTTP stack. + private static String sDatabaseDirectory; + private static String sCacheDirectory; + private CookieSyncManager(Context context) { super(context, "CookieSyncManager"); } @@ -77,11 +82,7 @@ public final class CookieSyncManager extends WebSyncManager { * @return CookieSyncManager */ public static synchronized CookieSyncManager getInstance() { - if (sRef == null) { - throw new IllegalStateException( - "CookieSyncManager::createInstance() needs to be called " - + "before CookieSyncManager::getInstance()"); - } + checkInstanceIsCreated(); return sRef; } @@ -92,8 +93,11 @@ public final class CookieSyncManager extends WebSyncManager { */ public static synchronized CookieSyncManager createInstance( Context context) { + Context appContext = context.getApplicationContext(); if (sRef == null) { - sRef = new CookieSyncManager(context.getApplicationContext()); + sRef = new CookieSyncManager(appContext); + sDatabaseDirectory = appContext.getDatabasePath("dummy").getParent(); + sCacheDirectory = appContext.getCacheDir().getAbsolutePath(); } return sRef; } @@ -210,4 +214,30 @@ public final class CookieSyncManager extends WebSyncManager { } } } + + private static void checkInstanceIsCreated() { + if (sRef == null) { + throw new IllegalStateException( + "CookieSyncManager::createInstance() needs to be called " + + "before CookieSyncManager::getInstance()"); + } + } + + /** + * Called by JNI. Gets the application's database directory, excluding the trailing slash. + * @return String The application's database directory + */ + private static synchronized String getDatabaseDirectory() { + checkInstanceIsCreated(); + return sDatabaseDirectory; + } + + /** + * Called by JNI. Gets the application's cache directory, excluding the trailing slash. + * @return String The application's cache directory + */ + private static synchronized String getCacheDirectory() { + checkInstanceIsCreated(); + return sCacheDirectory; + } } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 908a6ab..68fa5c3 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -6047,7 +6047,7 @@ public class WebView extends AbsoluteLayout } private void doMotionUp(int contentX, int contentY) { - if (mLogEvent && nativeMotionUp(contentX, contentY, mNavSlop)) { + if (nativeMotionUp(contentX, contentY, mNavSlop) && mLogEvent) { EventLog.writeEvent(EventLogTags.BROWSER_SNAP_CENTER); } if (nativeHasCursorNode() && !nativeCursorIsTextInput()) { diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 1c8e2cd..cd6c81e 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -260,9 +260,11 @@ final class WebViewCore { * Given mimeType, check whether it's supported in Android media framework. * mimeType could be such as "audio/ogg" and "video/mp4". */ - /* package */ static boolean supportsMimeType(String mimeType) { - return MediaFile.getFileTypeForMimeType(mimeType) > 0; + /* package */ static boolean isSupportedMediaMimeType(String mimeType) { + int fileType = MediaFile.getFileTypeForMimeType(mimeType); + return MediaFile.isAudioFileType(fileType) || MediaFile.isVideoFileType(fileType); } + /** * Add an error message to the client's console. * @param message The message to add diff --git a/core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java b/core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java deleted file mode 100644 index 200d49f..0000000 --- a/core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.view; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.os.Bundle; -import android.preference.CheckBoxPreference; -import android.preference.Preference; -import android.preference.PreferenceActivity; -import android.preference.PreferenceCategory; -import android.preference.PreferenceScreen; -import android.provider.Settings; -import android.text.TextUtils; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.InputMethodSubtype; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -public class InputMethodAndSubtypeEnabler extends PreferenceActivity { - - private boolean mHaveHardKeyboard; - - private List<InputMethodInfo> mInputMethodProperties; - - private final TextUtils.SimpleStringSplitter mStringColonSplitter - = new TextUtils.SimpleStringSplitter(':'); - - private String mLastInputMethodId; - private String mLastTickedInputMethodId; - - private AlertDialog mDialog = null; - - @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); - Configuration config = getResources().getConfiguration(); - mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY); - onCreateIMM(); - setPreferenceScreen(createPreferenceHierarchy()); - } - - @Override - protected void onResume() { - super.onResume(); - loadInputMethodSubtypeList(); - } - - @Override - protected void onPause() { - super.onPause(); - saveInputMethodSubtypeList(); - } - - @Override - public boolean onPreferenceTreeClick( - PreferenceScreen preferenceScreen, Preference preference) { - - if (preference instanceof CheckBoxPreference) { - final CheckBoxPreference chkPref = (CheckBoxPreference) preference; - final String id = chkPref.getKey(); - // TODO: Check subtype or not here - if (chkPref.isChecked()) { - InputMethodInfo selImi = null; - final int N = mInputMethodProperties.size(); - for (int i = 0; i < N; i++) { - InputMethodInfo imi = mInputMethodProperties.get(i); - if (id.equals(imi.getId())) { - selImi = imi; - if (isSystemIme(imi)) { - setSubtypesPreferenceEnabled(id, true); - // This is a built-in IME, so no need to warn. - mLastTickedInputMethodId = id; - return super.onPreferenceTreeClick(preferenceScreen, preference); - } - break; - } - } - if (selImi == null) { - return super.onPreferenceTreeClick(preferenceScreen, preference); - } - chkPref.setChecked(false); - if (mDialog == null) { - mDialog = (new AlertDialog.Builder(this)) - .setTitle(android.R.string.dialog_alert_title) - .setIcon(android.R.drawable.ic_dialog_alert) - .setCancelable(true) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - chkPref.setChecked(true); - setSubtypesPreferenceEnabled(id, true); - mLastTickedInputMethodId = id; - } - - }) - .setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - } - - }) - .create(); - } else { - if (mDialog.isShowing()) { - mDialog.dismiss(); - } - } - mDialog.setMessage(getResources().getString( - com.android.internal.R.string.ime_enabler_security_warning, - selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager()))); - mDialog.show(); - } else { - if (id.equals(mLastTickedInputMethodId)) { - mLastTickedInputMethodId = null; - } - setSubtypesPreferenceEnabled(id, false); - } - } - return super.onPreferenceTreeClick(preferenceScreen, preference); - } - - @Override - public void onDestroy() { - super.onDestroy(); - if (mDialog != null) { - mDialog.dismiss(); - mDialog = null; - } - } - - private void onCreateIMM() { - InputMethodManager imm = (InputMethodManager) getSystemService( - Context.INPUT_METHOD_SERVICE); - - // TODO: Change mInputMethodProperties to Map - mInputMethodProperties = imm.getInputMethodList(); - - mLastInputMethodId = Settings.Secure.getString(getContentResolver(), - Settings.Secure.DEFAULT_INPUT_METHOD); - } - - private PreferenceScreen createPreferenceHierarchy() { - // Root - PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this); - - int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size()); - // TODO: Use iterator. - for (int i = 0; i < N; ++i) { - PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(this); - root.addPreference(keyboardSettingsCategory); - InputMethodInfo property = mInputMethodProperties.get(i); - String prefKey = property.getId(); - - PackageManager pm = getPackageManager(); - CharSequence label = property.loadLabel(pm); - boolean systemIME = isSystemIme(property); - - keyboardSettingsCategory.setTitle(label); - - // Add a check box. - // Don't show the toggle if it's the only keyboard in the system, or it's a system IME. - if (mHaveHardKeyboard || (N > 1 && !systemIME)) { - CheckBoxPreference chkbxPref = new CheckBoxPreference(this); - chkbxPref.setKey(prefKey); - chkbxPref.setTitle(label); - keyboardSettingsCategory.addPreference(chkbxPref); - } - - ArrayList<InputMethodSubtype> subtypes = property.getSubtypes(); - if (subtypes.size() > 0) { - PreferenceCategory subtypesCategory = new PreferenceCategory(this); - subtypesCategory.setTitle(getResources().getString( - com.android.internal.R.string.ime_enabler_subtype_title, label)); - root.addPreference(subtypesCategory); - for (InputMethodSubtype subtype: subtypes) { - CharSequence subtypeLabel; - int nameResId = subtype.getNameResId(); - if (nameResId != 0) { - subtypeLabel = pm.getText(property.getPackageName(), nameResId, - property.getServiceInfo().applicationInfo); - } else { - int modeResId = subtype.getModeResId(); - CharSequence language = subtype.getLocale(); - CharSequence mode = modeResId == 0 ? null - : pm.getText(property.getPackageName(), modeResId, - property.getServiceInfo().applicationInfo); - // TODO: Use more friendly Title and UI - subtypeLabel = (mode == null ? "" : mode) + "," - + (language == null ? "" : language); - } - CheckBoxPreference chkbxPref = new CheckBoxPreference(this); - chkbxPref.setKey(prefKey + subtype.hashCode()); - chkbxPref.setTitle(subtypeLabel); - chkbxPref.setSummary(label); - subtypesCategory.addPreference(chkbxPref); - } - } - } - return root; - } - - private void loadInputMethodSubtypeList() { - final HashSet<String> enabled = new HashSet<String>(); - String enabledStr = Settings.Secure.getString(getContentResolver(), - Settings.Secure.ENABLED_INPUT_METHODS); - if (enabledStr != null) { - final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; - splitter.setString(enabledStr); - while (splitter.hasNext()) { - enabled.add(splitter.next()); - } - } - - // Update the statuses of the Check Boxes. - int N = mInputMethodProperties.size(); - // TODO: Use iterator. - for (int i = 0; i < N; ++i) { - final String id = mInputMethodProperties.get(i).getId(); - CheckBoxPreference pref = (CheckBoxPreference) findPreference( - mInputMethodProperties.get(i).getId()); - if (pref != null) { - boolean isEnabled = enabled.contains(id); - pref.setChecked(isEnabled); - setSubtypesPreferenceEnabled(id, isEnabled); - } - } - mLastTickedInputMethodId = null; - } - - private void saveInputMethodSubtypeList() { - StringBuilder builder = new StringBuilder(); - StringBuilder disabledSysImes = new StringBuilder(); - - int firstEnabled = -1; - int N = mInputMethodProperties.size(); - for (int i = 0; i < N; ++i) { - final InputMethodInfo property = mInputMethodProperties.get(i); - final String id = property.getId(); - CheckBoxPreference pref = (CheckBoxPreference) findPreference(id); - boolean currentInputMethod = id.equals(mLastInputMethodId); - boolean systemIme = isSystemIme(property); - // TODO: Append subtypes by using the separator ";" - if (((N == 1 || systemIme) && !mHaveHardKeyboard) - || (pref != null && pref.isChecked())) { - if (builder.length() > 0) builder.append(':'); - builder.append(id); - if (firstEnabled < 0) { - firstEnabled = i; - } - } else if (currentInputMethod) { - mLastInputMethodId = mLastTickedInputMethodId; - } - // If it's a disabled system ime, add it to the disabled list so that it - // doesn't get enabled automatically on any changes to the package list - if (pref != null && !pref.isChecked() && systemIme && mHaveHardKeyboard) { - if (disabledSysImes.length() > 0) disabledSysImes.append(":"); - disabledSysImes.append(id); - } - } - - // If the last input method is unset, set it as the first enabled one. - if (TextUtils.isEmpty(mLastInputMethodId)) { - if (firstEnabled >= 0) { - mLastInputMethodId = mInputMethodProperties.get(firstEnabled).getId(); - } else { - mLastInputMethodId = null; - } - } - - Settings.Secure.putString(getContentResolver(), - Settings.Secure.ENABLED_INPUT_METHODS, builder.toString()); - Settings.Secure.putString(getContentResolver(), - Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, disabledSysImes.toString()); - Settings.Secure.putString(getContentResolver(), - Settings.Secure.DEFAULT_INPUT_METHOD, - mLastInputMethodId != null ? mLastInputMethodId : ""); - } - - private void setSubtypesPreferenceEnabled(String id, boolean enabled) { - PreferenceScreen preferenceScreen = getPreferenceScreen(); - final int N = mInputMethodProperties.size(); - // TODO: Use iterator. - for (int i = 0; i < N; i++) { - InputMethodInfo imi = mInputMethodProperties.get(i); - if (id.equals(imi.getId())) { - for (InputMethodSubtype subtype: imi.getSubtypes()) { - preferenceScreen.findPreference(id + subtype.hashCode()).setEnabled(enabled); - } - } - } - } - - private boolean isSystemIme(InputMethodInfo property) { - return (property.getServiceInfo().applicationInfo.flags - & ApplicationInfo.FLAG_SYSTEM) != 0; - } -} |
