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>
+ *   &lt;intent-filter&gt;
+ *     &lt;action android:name="android.content.SyncAdapter" /&gt;
+ *   &lt;/intent-filter&gt;
+ *   &lt;meta-data android:name="android.content.SyncAdapter"
+ *             android:resource="@xml/syncadapter" /&gt;
+ * </pre>
+ * The <code>android:resource</code> attribute must point to a resource that looks like:
+ * <pre>
+ * &lt;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"
+ * /&gt;
+ * </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();
+                }
             }
         }