Merge change 7686 into donut

* changes:
  MediaScanner: Add check for null object in empty title handling code.
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 359cdac..906361c 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -139,8 +139,8 @@
     
     // A weak map of drawables we've gotten from other packages, so we don't load them
     // more than once.
-    private final WeakHashMap<String, Drawable> mOutsideDrawablesCache =
-            new WeakHashMap<String, Drawable>();
+    private final WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache =
+            new WeakHashMap<String, Drawable.ConstantState>();
 
     // Last known IME options value for the search edit text.
     private int mSearchAutoCompleteImeOptions;
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index f2325d0..593b7b7 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -61,8 +61,8 @@
     private SearchDialog mSearchDialog;
     private SearchableInfo mSearchable;
     private Context mProviderContext;
-    private WeakHashMap<String, Drawable> mOutsideDrawablesCache;
-    private SparseArray<Drawable> mBackgroundsCache;
+    private WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache;
+    private SparseArray<Drawable.ConstantState> mBackgroundsCache;
     private boolean mGlobalSearchMode;
 
     // Cached column indexes, updated when the cursor changes.
@@ -97,8 +97,10 @@
      */
     private static final long DELETE_KEY_POST_DELAY = 500L;
 
-    public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable,
-            WeakHashMap<String, Drawable> outsideDrawablesCache, boolean globalSearchMode) {
+    public SuggestionsAdapter(Context context, SearchDialog searchDialog,
+            SearchableInfo searchable,
+            WeakHashMap<String, Drawable.ConstantState> outsideDrawablesCache,
+            boolean globalSearchMode) {
         super(context,
                 com.android.internal.R.layout.search_dropdown_item_icons_2line,
                 null,   // no initial cursor
@@ -112,7 +114,7 @@
         mProviderContext = mSearchable.getProviderContext(mContext, activityContext);
 
         mOutsideDrawablesCache = outsideDrawablesCache;
-        mBackgroundsCache = new SparseArray<Drawable>();
+        mBackgroundsCache = new SparseArray<Drawable.ConstantState>();
         mGlobalSearchMode = globalSearchMode;
 
         mStartSpinnerRunnable = new Runnable() {
@@ -345,11 +347,10 @@
         if (backgroundColor == 0) {
             return null;
         } else {
-            Drawable cachedBg = mBackgroundsCache.get(backgroundColor);
+            Drawable.ConstantState cachedBg = mBackgroundsCache.get(backgroundColor);
             if (cachedBg != null) {
                 if (DBG) Log.d(LOG_TAG, "Background cache hit for color " + backgroundColor);
-                // copy the drawable so that they don't share states
-                return cachedBg.getConstantState().newDrawable();
+                return cachedBg.newDrawable();
             }
             if (DBG) Log.d(LOG_TAG, "Creating new background for color " + backgroundColor);
             ColorDrawable transparent = new ColorDrawable(0);
@@ -358,7 +359,7 @@
             newBg.addState(new int[]{android.R.attr.state_selected}, transparent);
             newBg.addState(new int[]{android.R.attr.state_pressed}, transparent);
             newBg.addState(new int[]{}, background);
-            mBackgroundsCache.put(backgroundColor, newBg);
+            mBackgroundsCache.put(backgroundColor, newBg.getConstantState());
             return newBg;
         }
     }
@@ -523,12 +524,13 @@
         }
 
         // First, check the cache.
-        Drawable drawable = mOutsideDrawablesCache.get(drawableId);
-        if (drawable != null) {
+        Drawable.ConstantState cached = mOutsideDrawablesCache.get(drawableId);
+        if (cached != null) {
             if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId);
-            return drawable;
+            return cached.newDrawable();
         }
 
+        Drawable drawable = null;
         try {
             // Not cached, try using it as a plain resource ID in the provider's context.
             int resourceId = Integer.parseInt(drawableId);
@@ -560,7 +562,7 @@
             // If we got a drawable for this resource id, then stick it in the
             // map so we don't do this lookup again.
             if (drawable != null) {
-                mOutsideDrawablesCache.put(drawableId, drawable);
+                mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
             }
         } catch (Resources.NotFoundException nfe) {
             if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId);
@@ -615,12 +617,14 @@
         String componentIconKey = component.flattenToShortString();
         // Using containsKey() since we also store null values.
         if (mOutsideDrawablesCache.containsKey(componentIconKey)) {
-            return mOutsideDrawablesCache.get(componentIconKey);
+            Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey);
+            return cached == null ? null : cached.newDrawable();
         }
         // Then try the activity or application icon
         Drawable drawable = getActivityIcon(component);
         // Stick it in the cache so we don't do this lookup again.
-        mOutsideDrawablesCache.put(componentIconKey, drawable);
+        Drawable.ConstantState toCache = drawable == null ? null : drawable.getConstantState();
+        mOutsideDrawablesCache.put(componentIconKey, toCache);
         return drawable;
     }
 
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index ebe556e..08e3a40 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -38,7 +38,12 @@
     private static final String TAG = "CompatibilityInfo";
     
     /** default compatibility info object for compatible applications */
-    public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo(); 
+    public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() {
+        @Override
+        public void setExpandable(boolean expandable) {
+            throw new UnsupportedOperationException("trying to change default compatibility info");
+        }
+    };
 
     /**
      * The default width of the screen in portrait mode. 
@@ -191,7 +196,7 @@
     @Override
     public String toString() {
         return "CompatibilityInfo{scale=" + applicationScale +
-                ", compatibility flag=" + mCompatibilityFlags + "}"; 
+                ", supports screen=" + supportsScreen() + "}";
     }
 
     /**
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index eab3799..301d604 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -497,8 +497,12 @@
     void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
         synchronized (this) {
             int oldSoftInputMode = mWindowAttributes.softInputMode;
+            // preserve compatible window flag if exists.
+            int compatibleWindowFlag =
+                mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
             mWindowAttributes.copyFrom(attrs);
-
+            mWindowAttributes.flags |= compatibleWindowFlag;
+            
             if (newView) {
                 mSoftInputMode = attrs.softInputMode;
                 requestLayout();
@@ -1301,7 +1305,8 @@
                 if (DEBUG_DRAW) {
                     Context cxt = mView.getContext();
                     Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +
-                            ", metrics=" + mView.getContext().getResources().getDisplayMetrics());
+                            ", metrics=" + cxt.getResources().getDisplayMetrics() +
+                            ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());
                 }
                 int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
                 try {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e96a15b..ba3bfa7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -986,6 +986,9 @@
                 sb.append(" or=");
                 sb.append(screenOrientation);
             }
+            if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+                sb.append(" compatible=true");
+            }
             sb.append('}');
             return sb.toString();
         }
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 64cdb5b..099c4d1 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -286,6 +286,7 @@
 {
     if (jniData) {
         SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
+        env->DeleteGlobalRef(pSynthData->tts_ref);
         delete pSynthData;
     }
 }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 4baf202..5425709 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1891,7 +1891,7 @@
                         break;
                     case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
                         animAttr = enter
-                        ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
+                                ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
                                 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
                         break;
                 }
@@ -7232,17 +7232,27 @@
 
     public static WindowManager.LayoutParams findAnimations(
             ArrayList<AppWindowToken> order,
-            ArrayList<AppWindowToken> tokenList1,
-            ArrayList<AppWindowToken> tokenList2) {
+            ArrayList<AppWindowToken> openingTokenList1,
+            ArrayList<AppWindowToken> closingTokenList2) {
         // We need to figure out which animation to use...
+
+        // First, check if there is a compatible window in opening/closing
+        // apps, and use it if exists.
         WindowManager.LayoutParams animParams = null;
         int animSrc = 0;
-
+        animParams = findCompatibleWindowParams(openingTokenList1);
+        if (animParams == null) {
+            animParams = findCompatibleWindowParams(closingTokenList2);
+        }
+        if (animParams != null) {
+            return animParams;
+        }
+        
         //Log.i(TAG, "Looking for animations...");
         for (int i=order.size()-1; i>=0; i--) {
             AppWindowToken wtoken = order.get(i);
             //Log.i(TAG, "Token " + wtoken + " with " + wtoken.windows.size() + " windows");
-            if (tokenList1.contains(wtoken) || tokenList2.contains(wtoken)) {
+            if (openingTokenList1.contains(wtoken) || closingTokenList2.contains(wtoken)) {
                 int j = wtoken.windows.size();
                 while (j > 0) {
                     j--;
@@ -7270,6 +7280,21 @@
         return animParams;
     }
 
+    private static LayoutParams findCompatibleWindowParams(ArrayList<AppWindowToken> tokenList) {
+        for (int appCount = tokenList.size() - 1; appCount >= 0; appCount--) {
+            AppWindowToken wtoken = tokenList.get(appCount);
+            // Just checking one window is sufficient as all windows have the compatible flag 
+            // if the application is in compatibility mode.
+            if (wtoken.windows.size() > 0) {
+                WindowManager.LayoutParams params = wtoken.windows.get(0).mAttrs;
+                if ((params.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+                    return params;
+                }
+            }
+        }
+        return null;
+    }
+
     // -------------------------------------------------------------
     // DummyAnimation
     // -------------------------------------------------------------
@@ -9277,16 +9302,10 @@
             // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
             mWidth = width;
         }
-        
-        @Override
-        public boolean willChangeTransformationMatrix() {
-            return true;
-        }
 
         @Override
-        public boolean willChangeBounds() {
-            return true;
+        public int getZAdjustment() {
+            return Animation.ZORDER_TOP;
         }
     }
 }
-