summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/nfc/NdefTagConnection.java16
-rw-r--r--core/java/android/nfc/NfcAdapter.java62
-rw-r--r--core/java/android/nfc/RawTagConnection.java39
-rw-r--r--core/java/android/preference/PreferenceFragment.java2
-rw-r--r--core/java/android/provider/Settings.java14
-rw-r--r--core/java/android/webkit/BrowserFrame.java33
-rw-r--r--core/java/android/webkit/CookieSyncManager.java42
-rw-r--r--core/java/android/webkit/WebView.java2
-rw-r--r--core/java/android/webkit/WebViewCore.java6
-rw-r--r--core/java/com/android/internal/view/InputMethodAndSubtypeEnabler.java319
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;
- }
-}