Merge "Righting a wrong."
diff --git a/api/current.txt b/api/current.txt
index 01b07a6..b962234 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5770,6 +5770,7 @@
ctor public SyncAdapterType(android.os.Parcel);
method public boolean allowParallelSyncs();
method public int describeContents();
+ method public java.lang.String getSettingsActivity();
method public boolean isAlwaysSyncable();
method public boolean isUserVisible();
method public static android.content.SyncAdapterType newKey(java.lang.String, java.lang.String);
@@ -24493,6 +24494,7 @@
method public android.content.ComponentName getComponent();
method public java.lang.String getId();
method public java.lang.String getPackageName();
+ method public android.content.pm.ServiceInfo getServiceInfo();
method public java.lang.String getSettingsActivity();
method public android.view.textservice.SpellCheckerSubtype getSubtypeAt(int);
method public int getSubtypeCount();
@@ -24518,6 +24520,7 @@
public final class SpellCheckerSubtype implements android.os.Parcelable {
ctor public SpellCheckerSubtype(int, java.lang.String, java.lang.String);
method public int describeContents();
+ method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
method public java.lang.String getExtraValue();
method public java.lang.String getLocale();
method public int getNameResId();
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index fcc19a2..6bffed7 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -34,6 +34,51 @@
* If a cancelSync() is received that matches an existing sync operation then the thread
* that is running that sync operation will be interrupted, which will indicate to the thread
* that the sync has been canceled.
+ * <p>
+ * In order to be a sync adapter one must extend this class, provide implementations for the
+ * abstract methods and write a service that returns the result of {@link #getSyncAdapterBinder()}
+ * in the service's {@link android.app.Service#onBind(android.content.Intent)} when invoked
+ * with an intent with action <code>android.content.SyncAdapter</code>. This service
+ * must specify the following intent filter and metadata tags in its AndroidManifest.xml file
+ * <pre>
+ * <intent-filter>
+ * <action android:name="android.content.SyncAdapter" />
+ * </intent-filter>
+ * <meta-data android:name="android.content.SyncAdapter"
+ * android:resource="@xml/syncadapter" />
+ * </pre>
+ * The <code>android:resource</code> attribute must point to a resource that looks like:
+ * <pre>
+ * <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:contentAuthority="authority"
+ * android:accountType="accountType"
+ * android:userVisible="true|false"
+ * android:supportsUploading="true|false"
+ * android:allowParallelSyncs="true|false"
+ * android:isAlwaysSyncable="true|false"
+ * android:syncAdapterSettingsAction="ACTION_OF_SETTINGS_ACTIVITY"
+ * />
+ * </pre>
+ * <ul>
+ * <li>The <code>android:contentAuthority</code> and <code>android:accountType</code> attributes
+ * indicate which content authority and for which account types this sync adapter serves.
+ * <li><code>android:userVisible</code> defaults to true and controls whether or not this sync
+ * adapter shows up in the Sync Settings screen.
+ * <li><code>android:supportsUploading</code> defaults
+ * to true and if true an upload-only sync will be requested for all syncadapters associated
+ * with an authority whenever that authority's content provider does a
+ * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}
+ * with syncToNetwork set to true.
+ * <li><code>android:allowParallelSyncs</code> defaults to false and if true indicates that
+ * the sync adapter can handle syncs for multiple accounts at the same time. Otherwise
+ * the SyncManager will wait until the sync adapter is not in use before requesting that
+ * it sync an account's data.
+ * <li><code>android:isAlwaysSyncable</code> defaults to false and if true tells the SyncManager
+ * to intialize the isSyncable state to 1 for that sync adapter for each account that is added.
+ * <li><code>android:syncAdapterSettingsAction</code> defaults to null and if supplied it
+ * specifies an Intent action of an activity that can be used to adjust the sync adapter's
+ * sync settings. The activity must live in the same package as the sync adapter.
+ * </ul>
*/
public abstract class AbstractThreadedSyncAdapter {
/**
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index b85346e..8a16ac9 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -32,6 +32,7 @@
private final boolean supportsUploading;
private final boolean isAlwaysSyncable;
private final boolean allowParallelSyncs;
+ private final String settingsActivity;
public SyncAdapterType(String authority, String accountType, boolean userVisible,
boolean supportsUploading) {
@@ -47,6 +48,7 @@
this.supportsUploading = supportsUploading;
this.isAlwaysSyncable = false;
this.allowParallelSyncs = false;
+ this.settingsActivity = null;
this.isKey = false;
}
@@ -54,7 +56,8 @@
public SyncAdapterType(String authority, String accountType, boolean userVisible,
boolean supportsUploading,
boolean isAlwaysSyncable,
- boolean allowParallelSyncs) {
+ boolean allowParallelSyncs,
+ String settingsActivity) {
if (TextUtils.isEmpty(authority)) {
throw new IllegalArgumentException("the authority must not be empty: " + authority);
}
@@ -67,6 +70,7 @@
this.supportsUploading = supportsUploading;
this.isAlwaysSyncable = isAlwaysSyncable;
this.allowParallelSyncs = allowParallelSyncs;
+ this.settingsActivity = settingsActivity;
this.isKey = false;
}
@@ -83,6 +87,7 @@
this.supportsUploading = true;
this.isAlwaysSyncable = false;
this.allowParallelSyncs = false;
+ this.settingsActivity = null;
this.isKey = true;
}
@@ -131,6 +136,18 @@
return isAlwaysSyncable;
}
+ /**
+ * @return The activity to use to invoke this SyncAdapter's settings activity.
+ * May be null.
+ */
+ public String getSettingsActivity() {
+ if (isKey) {
+ throw new IllegalStateException(
+ "this method is not allowed to be called when this is a key");
+ }
+ return settingsActivity;
+ }
+
public static SyncAdapterType newKey(String authority, String accountType) {
return new SyncAdapterType(authority, accountType);
}
@@ -163,6 +180,7 @@
+ ", supportsUploading=" + supportsUploading
+ ", isAlwaysSyncable=" + isAlwaysSyncable
+ ", allowParallelSyncs=" + allowParallelSyncs
+ + ", settingsActivity=" + settingsActivity
+ "}";
}
}
@@ -182,6 +200,7 @@
dest.writeInt(supportsUploading ? 1 : 0);
dest.writeInt(isAlwaysSyncable ? 1 : 0);
dest.writeInt(allowParallelSyncs ? 1 : 0);
+ dest.writeString(settingsActivity);
}
public SyncAdapterType(Parcel source) {
@@ -191,7 +210,8 @@
source.readInt() != 0,
source.readInt() != 0,
source.readInt() != 0,
- source.readInt() != 0);
+ source.readInt() != 0,
+ source.readString());
}
public static final Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java
index 33a713b..7b643a0 100644
--- a/core/java/android/content/SyncAdaptersCache.java
+++ b/core/java/android/content/SyncAdaptersCache.java
@@ -66,8 +66,11 @@
final boolean allowParallelSyncs =
sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_allowParallelSyncs,
false);
+ final String settingsActivity =
+ sa.getString(com.android.internal.R.styleable
+ .SyncAdapter_settingsActivity);
return new SyncAdapterType(authority, accountType, userVisible, supportsUploading,
- isAlwaysSyncable, allowParallelSyncs);
+ isAlwaysSyncable, allowParallelSyncs, settingsActivity);
} finally {
sa.recycle();
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 926d424..5b592e0 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -810,9 +810,9 @@
if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- fallback(true);
Log.e(LOG_TAG, "eglMakeCurrent failed " +
GLUtils.getEGLErrorString(sEgl.eglGetError()));
+ fallback(true);
return SURFACE_STATE_ERROR;
} else {
return SURFACE_STATE_UPDATED;
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index 89cb11c..9d8475d 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -24,7 +24,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -71,7 +70,6 @@
final PackageManager pm = context.getPackageManager();
int label = 0;
String settingsActivityComponent = null;
- int isDefaultResId = 0;
XmlResourceParser parser = null;
try {
@@ -221,6 +219,15 @@
return mService.loadIcon(pm);
}
+
+ /**
+ * Return the raw information about the Service implementing this
+ * spell checker. Do not modify the returned object.
+ */
+ public ServiceInfo getServiceInfo() {
+ return mService.serviceInfo;
+ }
+
/**
* Return the class name of an activity that provides a settings UI.
* You can launch this activity be starting it with
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index dbd3081..aeb3ba6 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -17,13 +17,16 @@
package android.view.textservice;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
/**
* This class is used to specify meta information of a subtype contained in a spell checker.
@@ -97,6 +100,48 @@
return false;
}
+ private static Locale constructLocaleFromString(String localeStr) {
+ if (TextUtils.isEmpty(localeStr))
+ return null;
+ String[] localeParams = localeStr.split("_", 3);
+ // The length of localeStr is guaranteed to always return a 1 <= value <= 3
+ // because localeStr is not empty.
+ if (localeParams.length == 1) {
+ return new Locale(localeParams[0]);
+ } else if (localeParams.length == 2) {
+ return new Locale(localeParams[0], localeParams[1]);
+ } else if (localeParams.length == 3) {
+ return new Locale(localeParams[0], localeParams[1], localeParams[2]);
+ }
+ return null;
+ }
+
+ /**
+ * @param context Context will be used for getting Locale and PackageManager.
+ * @param packageName The package name of the spell checker
+ * @param appInfo The application info of the spell checker
+ * @return a display name for this subtype. The string resource of the label (mSubtypeNameResId)
+ * can have only one %s in it. If there is, the %s part will be replaced with the locale's
+ * display name by the formatter. If there is not, this method simply returns the string
+ * specified by mSubtypeNameResId. If mSubtypeNameResId is not specified (== 0), it's up to the
+ * framework to generate an appropriate display name.
+ */
+ public CharSequence getDisplayName(
+ Context context, String packageName, ApplicationInfo appInfo) {
+ final Locale locale = constructLocaleFromString(mSubtypeLocale);
+ final String localeStr = locale != null ? locale.getDisplayName() : mSubtypeLocale;
+ if (mSubtypeNameResId == 0) {
+ return localeStr;
+ }
+ final CharSequence subtypeName = context.getPackageManager().getText(
+ packageName, mSubtypeNameResId, appInfo);
+ if (!TextUtils.isEmpty(subtypeName)) {
+ return String.format(subtypeName.toString(), localeStr);
+ } else {
+ return localeStr;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 5dca348..c85b2d9 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -72,27 +72,53 @@
* languages in settings will be returned.
* @return the spell checker session of the spell checker
*/
- // TODO: Add a method to get enabled spell checkers.
- // TODO: Handle referToSpellCheckerLanguageSettings
public SpellCheckerSession newSpellCheckerSession(Bundle bundle, Locale locale,
SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
if (listener == null) {
throw new NullPointerException();
}
- // TODO: set a proper locale instead of the dummy locale
- final String localeString = locale == null ? "en" : locale.toString();
+ if (!referToSpellCheckerLanguageSettings && locale == null) {
+ throw new IllegalArgumentException("Locale should not be null if you don't refer"
+ + " settings.");
+ }
final SpellCheckerInfo sci;
try {
- sci = sService.getCurrentSpellChecker(localeString);
+ sci = sService.getCurrentSpellChecker(null);
} catch (RemoteException e) {
return null;
}
if (sci == null) {
return null;
}
+ SpellCheckerSubtype subtypeInUse = null;
+ if (referToSpellCheckerLanguageSettings) {
+ subtypeInUse = getCurrentSpellCheckerSubtype(true);
+ if (subtypeInUse == null) {
+ return null;
+ }
+ if (locale != null) {
+ final String subtypeLocale = subtypeInUse.getLocale();
+ final String inputLocale = locale.toString();
+ if (subtypeLocale.length() < 2 || inputLocale.length() < 2
+ || !subtypeLocale.substring(0, 2).equals(inputLocale.substring(0, 2))) {
+ return null;
+ }
+ }
+ } else {
+ final String localeStr = locale.toString();
+ for (int i = 0; i < sci.getSubtypeCount(); ++i) {
+ final SpellCheckerSubtype subtype = sci.getSubtypeAt(i);
+ if (subtype.getLocale().equals(localeStr)) {
+ subtypeInUse = subtype;
+ }
+ }
+ }
+ if (subtypeInUse == null) {
+ return null;
+ }
final SpellCheckerSession session = new SpellCheckerSession(sci, sService, listener);
try {
- sService.getSpellCheckerService(sci.getId(), localeString,
+ sService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
session.getTextServicesSessionListener(),
session.getSpellCheckerSessionListener(), bundle);
} catch (RemoteException e) {
@@ -146,10 +172,11 @@
/**
* @hide
*/
- public SpellCheckerSubtype getCurrentSpellCheckerSubtype() {
+ public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+ boolean allowImplicitlySelectedSubtype) {
try {
// Passing null as a locale for ICS
- return sService.getCurrentSpellCheckerSubtype(null);
+ return sService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
} catch (RemoteException e) {
Log.e(TAG, "Error in getCurrentSpellCheckerSubtype: " + e);
return null;
@@ -161,10 +188,13 @@
*/
public void setSpellCheckerSubtype(SpellCheckerSubtype subtype) {
try {
+ final int hashCode;
if (subtype == null) {
- throw new NullPointerException("SpellCheckerSubtype is null.");
+ hashCode = 0;
+ } else {
+ hashCode = subtype.hashCode();
}
- sService.setCurrentSpellCheckerSubtype(null, subtype.hashCode());
+ sService.setCurrentSpellCheckerSubtype(null, hashCode);
} catch (RemoteException e) {
Log.e(TAG, "Error in setSpellCheckerSubtype:" + e);
}
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index b18af02..4882a12 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -30,7 +30,8 @@
*/
interface ITextServicesManager {
SpellCheckerInfo getCurrentSpellChecker(String locale);
- SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale);
+ SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+ String locale, boolean allowImplicitlySelectedSubtype);
oneway void getSpellCheckerService(String sciId, in String locale,
in ITextServicesSessionListener tsListener,
in ISpellCheckerSessionListener scListener, in Bundle bundle);
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a536961..93cbde5 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5110,6 +5110,10 @@
Defaults to false.
-->
<attr name="isAlwaysSyncable" format="boolean"/>
+ <!-- If provided, specifies the action of the settings
+ activity for this SyncAdapter.
+ -->
+ <attr name="settingsActivity"/>
</declare-styleable>
<!-- =============================== -->
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index df30e8c..923518d 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -481,6 +481,7 @@
bool mMarkerReached;
uint32_t mNewPosition;
uint32_t mUpdatePeriod;
+ bool mFlushed; // FIXME will be made obsolete by making flush() synchronous
uint32_t mFlags;
int mSessionId;
int mAuxEffectId;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index ac9b33b..79a01a3 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -608,6 +608,9 @@
if (mConnectedApi == api) {
drainQueueAndFreeBuffersLocked();
mConnectedApi = NO_CONNECTED_API;
+ mNextCrop.makeInvalid();
+ mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+ mNextTransform = 0;
mDequeueCondition.signal();
} else {
LOGE("disconnect: connected to another api (cur=%d, req=%d)",
@@ -1022,7 +1025,7 @@
mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
mCurrentTransform, mCurrentTexture,
prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
- mCurrentTransform, fifoSize, fifo.string()
+ mNextTransform, fifoSize, fifo.string()
);
result.append(buffer);
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 5a35b4d..710ef94 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -407,8 +407,15 @@
LOGV("SurfaceTextureClient::disconnect");
Mutex::Autolock lock(mMutex);
int err = mSurfaceTexture->disconnect(api);
- if (!err && api == NATIVE_WINDOW_API_CPU) {
- mConnectedToCpu = false;
+ if (!err) {
+ freeAllBuffers();
+ mReqFormat = 0;
+ mReqWidth = 0;
+ mReqHeight = 0;
+ mReqUsage = 0;
+ if (api == NATIVE_WINDOW_API_CPU) {
+ mConnectedToCpu = false;
+ }
}
return err;
}
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 3949c39..cecedb5 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -259,6 +259,7 @@
mMarkerReached = false;
mNewPosition = 0;
mUpdatePeriod = 0;
+ mFlushed = false;
mFlags = flags;
AudioSystem::acquireAudioSessionId(mSessionId);
@@ -337,6 +338,7 @@
audio_track_cblk_t* cblk = mCblk;
if (mActive == 0) {
+ mFlushed = false;
mActive = 1;
mNewPosition = cblk->server + mUpdatePeriod;
cblk->lock.lock();
@@ -437,6 +439,7 @@
mUpdatePeriod = 0;
if (!mActive) {
+ mFlushed = true;
mAudioTrack->flush();
// Release AudioTrack callback thread in case it was waiting for new buffers
// in AudioTrack::obtainBuffer()
@@ -655,7 +658,7 @@
{
if (position == 0) return BAD_VALUE;
AutoMutex lock(mLock);
- *position = mCblk->server;
+ *position = mFlushed ? 0 : mCblk->server;
return NO_ERROR;
}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 1f0016a..7e85230 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -675,6 +675,9 @@
setGLHooksThreadSpecific(&gHooksNoContext);
egl_tls_t::setContext(EGL_NO_CONTEXT);
}
+ } else {
+ // this will LOGE the error
+ result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
}
return result;
}
diff --git a/preloaded-classes b/preloaded-classes
index 1b2bfd5..31d49ce 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -324,7 +324,6 @@
android.ddm.DdmHandleThread
android.ddm.DdmRegister
android.debug.JNITest
-android.drm.DrmManagerClient
android.emoji.EmojiFactory
android.graphics.AvoidXfermode
android.graphics.Bitmap
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 5e54d61..5ffcdc5 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -764,12 +764,18 @@
public void scheduleTimeTickEvent() {
Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(System.currentTimeMillis());
+ final long currentTime = System.currentTimeMillis();
+ calendar.setTimeInMillis(currentTime);
calendar.add(Calendar.MINUTE, 1);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
-
- set(AlarmManager.RTC, calendar.getTimeInMillis(), mTimeTickSender);
+
+ // Schedule this event for the amount of time that it would take to get to
+ // the top of the next minute.
+ final long tickEventDelay = calendar.getTimeInMillis() - currentTime;
+
+ set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay,
+ mTimeTickSender);
}
public void scheduleDateChangedEvent() {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index c11755b..38bcebc 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -2018,8 +2018,9 @@
if (DEBUG) Slog.v(TAG, "Show switching menu");
final Context context = mContext;
-
final PackageManager pm = context.getPackageManager();
+ final boolean isScreenLocked = mKeyguardManager != null
+ && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
String lastInputMethodId = Settings.Secure.getString(context
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
@@ -2075,7 +2076,7 @@
final String subtypeHashCode = String.valueOf(subtype.hashCode());
// We show all enabled IMEs and subtypes when an IME is shown.
if (enabledSubtypeSet.contains(subtypeHashCode)
- && (mInputShown || !subtype.isAuxiliary())) {
+ && ((mInputShown && !isScreenLocked) || !subtype.isAuxiliary())) {
final CharSequence title;
final String mode = subtype.getMode();
title = TextUtils.concat(subtype.getDisplayName(context,
@@ -2162,8 +2163,7 @@
}
});
- if (showSubtypes && mKeyguardManager != null && !(mKeyguardManager.isKeyguardLocked()
- && mKeyguardManager.isKeyguardSecure())) {
+ if (showSubtypes && !isScreenLocked) {
mDialogBuilder.setPositiveButton(
com.android.internal.R.string.configure_input_methods,
new DialogInterface.OnClickListener() {
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index 321274f..f6c369e 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -131,6 +131,11 @@
if (DBG) Slog.d(TAG, "Add: " + compName);
try {
final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri);
+ if (sci.getSubtypeCount() <= 0) {
+ Slog.w(TAG, "Skipping text service " + compName
+ + ": it does not contain subtypes.");
+ continue;
+ }
list.add(sci);
map.put(sci.getId(), sci);
} catch (XmlPullParserException e) {
@@ -186,9 +191,11 @@
}
}
+ // TODO: Respect allowImplicitlySelectedSubtype
// TODO: Save SpellCheckerSubtype by supported languages.
@Override
- public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale) {
+ public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+ String locale, boolean allowImplicitlySelectedSubtype) {
synchronized (mSpellCheckerMap) {
final String subtypeHashCodeStr =
Settings.Secure.getString(mContext.getContentResolver(),
@@ -203,27 +210,40 @@
}
return null;
}
- if (TextUtils.isEmpty(subtypeHashCodeStr)) {
- if (DBG) {
- Slog.w(TAG, "Return first subtype in " + sci.getId());
- }
- // Return the first Subtype if there is no settings for the current subtype.
- return sci.getSubtypeAt(0);
+ final int hashCode;
+ if (!TextUtils.isEmpty(subtypeHashCodeStr)) {
+ hashCode = Integer.valueOf(subtypeHashCodeStr);
+ } else {
+ hashCode = 0;
}
- final int hashCode = Integer.valueOf(subtypeHashCodeStr);
+ if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
+ return null;
+ }
+ final String systemLocale =
+ mContext.getResources().getConfiguration().locale.toString();
+ SpellCheckerSubtype candidate = null;
for (int i = 0; i < sci.getSubtypeCount(); ++i) {
final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
- if (scs.hashCode() == hashCode) {
+ if (hashCode == 0) {
+ if (systemLocale.equals(locale)) {
+ return scs;
+ } else if (candidate == null) {
+ final String scsLocale = scs.getLocale();
+ if (systemLocale.length() >= 2
+ && scsLocale.length() >= 2
+ && systemLocale.substring(0, 2).equals(
+ scsLocale.substring(0, 2))) {
+ candidate = scs;
+ }
+ }
+ } else if (scs.hashCode() == hashCode) {
if (DBG) {
Slog.w(TAG, "Return subtype " + scs.hashCode());
}
return scs;
}
}
- if (DBG) {
- Slog.w(TAG, "Return first subtype in " + sci.getId());
- }
- return sci.getSubtypeAt(0);
+ return candidate;
}
}
@@ -396,10 +416,16 @@
Slog.w(TAG, "setCurrentSpellChecker: " + sciId);
}
if (TextUtils.isEmpty(sciId) || !mSpellCheckerMap.containsKey(sciId)) return;
+ final SpellCheckerInfo currentSci = getCurrentSpellChecker(null);
+ if (currentSci != null && currentSci.getId().equals(sciId)) {
+ // Do nothing if the current spell checker is same as new spell checker.
+ return;
+ }
final long ident = Binder.clearCallingIdentity();
try {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+ setCurrentSpellCheckerSubtypeLocked(0);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -410,21 +436,17 @@
Slog.w(TAG, "setCurrentSpellCheckerSubtype: " + hashCode);
}
final SpellCheckerInfo sci = getCurrentSpellChecker(null);
- if (sci == null) return;
- boolean found = false;
- for (int i = 0; i < sci.getSubtypeCount(); ++i) {
+ int tempHashCode = 0;
+ for (int i = 0; sci != null && i < sci.getSubtypeCount(); ++i) {
if(sci.getSubtypeAt(i).hashCode() == hashCode) {
- found = true;
+ tempHashCode = hashCode;
break;
}
}
- if (!found) {
- return;
- }
final long ident = Binder.clearCallingIdentity();
try {
Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode));
+ Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(tempHashCode));
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6fde361..598220f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2211,10 +2211,13 @@
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
- const uint32_t z = layer->drawingState().z;
- if (z >= minLayerZ && z <= maxLayerZ) {
- if (layer->isProtected()) {
- return INVALID_OPERATION;
+ const uint32_t flags = layer->drawingState().flags;
+ if (!(flags & ISurfaceComposer::eLayerHidden)) {
+ const uint32_t z = layer->drawingState().z;
+ if (z >= minLayerZ && z <= maxLayerZ) {
+ if (layer->isProtected()) {
+ return INVALID_OPERATION;
+ }
}
}
}
@@ -2270,9 +2273,12 @@
for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
- const uint32_t z = layer->drawingState().z;
- if (z >= minLayerZ && z <= maxLayerZ) {
- layer->drawForSreenShot();
+ const uint32_t flags = layer->drawingState().flags;
+ if (!(flags & ISurfaceComposer::eLayerHidden)) {
+ const uint32_t z = layer->drawingState().z;
+ if (z >= minLayerZ && z <= maxLayerZ) {
+ layer->drawForSreenShot();
+ }
}
}