Remove unnecessary allocations

Change-Id: Ia561a0a312ca2737d5afa742184f5392bb2f29a3
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4463b06..970d041 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4575,11 +4575,8 @@
     }
 
     boolean rootViewRequestFocus() {
-        View root = getRootView();
-        if (root != null) {
-            return root.requestFocus();
-        }
-        return false;
+        final View root = getRootView();
+        return root != null && root.requestFocus();
     }
 
     /**
@@ -13482,7 +13479,8 @@
             onAnimationStart();
         }
 
-        boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
+        final Transformation t = parent.getChildTransformation();
+        boolean more = a.getTransformation(drawingTime, t, 1f);
         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
             if (parent.mInvalidationTransformation == null) {
                 parent.mInvalidationTransformation = new Transformation();
@@ -13490,7 +13488,7 @@
             invalidationTransform = parent.mInvalidationTransformation;
             a.getTransformation(drawingTime, invalidationTransform, 1f);
         } else {
-            invalidationTransform = parent.mChildTransformation;
+            invalidationTransform = t;
         }
 
         if (more) {
@@ -13543,17 +13541,15 @@
             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
                 ViewGroup parentVG = (ViewGroup) mParent;
-                final boolean hasTransform =
-                        parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
-                if (hasTransform) {
-                    Transformation transform = parentVG.mChildTransformation;
-                    final int transformType = parentVG.mChildTransformation.getTransformationType();
+                final Transformation t = parentVG.getChildTransformation();
+                if (parentVG.getChildStaticTransformation(this, t)) {
+                    final int transformType = t.getTransformationType();
                     if (transformType != Transformation.TYPE_IDENTITY) {
                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
-                            alpha = transform.getAlpha();
+                            alpha = t.getAlpha();
                         }
                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
-                            displayList.setMatrix(transform.getMatrix());
+                            displayList.setMatrix(t.getMatrix());
                         }
                     }
                 }
@@ -13598,7 +13594,7 @@
         final int flags = parent.mGroupFlags;
 
         if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
-            parent.mChildTransformation.clear();
+            parent.getChildTransformation().clear();
             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
         }
 
@@ -13626,7 +13622,7 @@
             if (concatMatrix) {
                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
             }
-            transformToApply = parent.mChildTransformation;
+            transformToApply = parent.getChildTransformation();
         } else {
             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) ==
                     PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mDisplayList != null) {
@@ -13636,12 +13632,11 @@
             }
             if (!useDisplayListProperties &&
                     (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
-                final boolean hasTransform =
-                        parent.getChildStaticTransformation(this, parent.mChildTransformation);
+                final Transformation t = parent.getChildTransformation();
+                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
                 if (hasTransform) {
-                    final int transformType = parent.mChildTransformation.getTransformationType();
-                    transformToApply = transformType != Transformation.TYPE_IDENTITY ?
-                            parent.mChildTransformation : null;
+                    final int transformType = t.getTransformationType();
+                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
                 }
             }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b0fbe84..119ba72 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -128,7 +128,7 @@
      * A Transformation used when drawing children, to
      * apply on the child being drawn.
      */
-    final Transformation mChildTransformation = new Transformation();
+    private Transformation mChildTransformation;
 
     /**
      * Used to track the current invalidation region.
@@ -3211,6 +3211,13 @@
         return false;
     }
 
+    Transformation getChildTransformation() {
+        if (mChildTransformation == null) {
+            mChildTransformation = new Transformation();
+        }
+        return mChildTransformation;
+    }
+
     /**
      * {@hide}
      */
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index cc1309b..ddc8d82 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -25,11 +25,11 @@
 import android.graphics.drawable.TransitionDrawable;
 import android.os.Bundle;
 import android.os.Debug;
-import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.StrictMode;
 import android.text.Editable;
+import android.text.InputType;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
@@ -61,9 +61,12 @@
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CorrectionInfo;
 import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputConnectionWrapper;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.RemoteViews.OnClickHandler;
 
@@ -5613,54 +5616,139 @@
     @Override
     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
         if (isTextFilterEnabled()) {
-            // XXX we need to have the text filter created, so we can get an
-            // InputConnection to proxy to.  Unfortunately this means we pretty
-            // much need to make it as soon as a list view gets focus.
-            createTextFilter(false);
             if (mPublicInputConnection == null) {
                 mDefInputConnection = new BaseInputConnection(this, false);
-                mPublicInputConnection = new InputConnectionWrapper(
-                        mTextFilter.onCreateInputConnection(outAttrs), true) {
-                    @Override
-                    public boolean reportFullscreenMode(boolean enabled) {
-                        // Use our own input connection, since it is
-                        // the "real" one the IME is talking with.
-                        return mDefInputConnection.reportFullscreenMode(enabled);
-                    }
-
-                    @Override
-                    public boolean performEditorAction(int editorAction) {
-                        // The editor is off in its own window; we need to be
-                        // the one that does this.
-                        if (editorAction == EditorInfo.IME_ACTION_DONE) {
-                            InputMethodManager imm = (InputMethodManager)
-                                    getContext().getSystemService(
-                                            Context.INPUT_METHOD_SERVICE);
-                            if (imm != null) {
-                                imm.hideSoftInputFromWindow(getWindowToken(), 0);
-                            }
-                            return true;
-                        }
-                        return false;
-                    }
-
-                    @Override
-                    public boolean sendKeyEvent(KeyEvent event) {
-                        // Use our own input connection, since the filter
-                        // text view may not be shown in a window so has
-                        // no ViewAncestor to dispatch events with.
-                        return mDefInputConnection.sendKeyEvent(event);
-                    }
-                };
+                mPublicInputConnection = new InputConnectionWrapper(outAttrs);
             }
-            outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT
-                    | EditorInfo.TYPE_TEXT_VARIATION_FILTER;
+            outAttrs.inputType = EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_FILTER;
             outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
             return mPublicInputConnection;
         }
         return null;
     }
 
+    private class InputConnectionWrapper implements InputConnection {
+        private final EditorInfo mOutAttrs;
+        private InputConnection mTarget;
+
+        public InputConnectionWrapper(EditorInfo outAttrs) {
+            mOutAttrs = outAttrs;
+        }
+
+        private InputConnection getTarget() {
+            if (mTarget == null) {
+                mTarget = getTextFilterInput().onCreateInputConnection(mOutAttrs);
+            }
+            return mTarget;
+        }
+
+        @Override
+        public boolean reportFullscreenMode(boolean enabled) {
+            // Use our own input connection, since it is
+            // the "real" one the IME is talking with.
+            return mDefInputConnection.reportFullscreenMode(enabled);
+        }
+
+        @Override
+        public boolean performEditorAction(int editorAction) {
+            // The editor is off in its own window; we need to be
+            // the one that does this.
+            if (editorAction == EditorInfo.IME_ACTION_DONE) {
+                InputMethodManager imm = (InputMethodManager)
+                        getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+                if (imm != null) {
+                    imm.hideSoftInputFromWindow(getWindowToken(), 0);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public boolean sendKeyEvent(KeyEvent event) {
+            // Use our own input connection, since the filter
+            // text view may not be shown in a window so has
+            // no ViewAncestor to dispatch events with.
+            return mDefInputConnection.sendKeyEvent(event);
+        }
+
+        public CharSequence getTextBeforeCursor(int n, int flags) {
+            if (mTarget == null) return "";
+            return mTarget.getTextBeforeCursor(n, flags);
+        }
+
+        public CharSequence getTextAfterCursor(int n, int flags) {
+            if (mTarget == null) return "";
+            return mTarget.getTextAfterCursor(n, flags);
+        }
+
+        public CharSequence getSelectedText(int flags) {
+            if (mTarget == null) return "";
+            return mTarget.getSelectedText(flags);
+        }
+
+        public int getCursorCapsMode(int reqModes) {
+            if (mTarget == null) return InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
+            return mTarget.getCursorCapsMode(reqModes);
+        }
+
+        public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
+            return getTarget().getExtractedText(request, flags);
+        }
+
+        public boolean deleteSurroundingText(int beforeLength, int afterLength) {
+            return getTarget().deleteSurroundingText(beforeLength, afterLength);
+        }
+
+        public boolean setComposingText(CharSequence text, int newCursorPosition) {
+            return getTarget().setComposingText(text, newCursorPosition);
+        }
+
+        public boolean setComposingRegion(int start, int end) {
+            return getTarget().setComposingRegion(start, end);
+        }
+
+        public boolean finishComposingText() {
+            return mTarget == null || mTarget.finishComposingText();
+        }
+
+        public boolean commitText(CharSequence text, int newCursorPosition) {
+            return getTarget().commitText(text, newCursorPosition);
+        }
+
+        public boolean commitCompletion(CompletionInfo text) {
+            return getTarget().commitCompletion(text);
+        }
+
+        public boolean commitCorrection(CorrectionInfo correctionInfo) {
+            return getTarget().commitCorrection(correctionInfo);
+        }
+
+        public boolean setSelection(int start, int end) {
+            return getTarget().setSelection(start, end);
+        }
+
+        public boolean performContextMenuAction(int id) {
+            return getTarget().performContextMenuAction(id);
+        }
+
+        public boolean beginBatchEdit() {
+            return getTarget().beginBatchEdit();
+        }
+
+        public boolean endBatchEdit() {
+            return getTarget().endBatchEdit();
+        }
+
+        public boolean clearMetaKeyStates(int states) {
+            return getTarget().clearMetaKeyStates(states);
+        }
+
+        public boolean performPrivateCommand(String action, Bundle data) {
+            return getTarget().performPrivateCommand(action, data);
+        }
+    }
+
     /**
      * For filtering we proxy an input connection to an internal text editor,
      * and this allows the proxying to happen.
@@ -5677,23 +5765,11 @@
      */
     private void createTextFilter(boolean animateEntrance) {
         if (mPopup == null) {
-            Context c = getContext();
-            PopupWindow p = new PopupWindow(c);
-            LayoutInflater layoutInflater = (LayoutInflater)
-                    c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            mTextFilter = (EditText) layoutInflater.inflate(
-                    com.android.internal.R.layout.typing_filter, null);
-            // For some reason setting this as the "real" input type changes
-            // the text view in some way that it doesn't work, and I don't
-            // want to figure out why this is.
-            mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT
-                    | EditorInfo.TYPE_TEXT_VARIATION_FILTER);
-            mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
-            mTextFilter.addTextChangedListener(this);
+            PopupWindow p = new PopupWindow(getContext());
             p.setFocusable(false);
             p.setTouchable(false);
             p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
-            p.setContentView(mTextFilter);
+            p.setContentView(getTextFilterInput());
             p.setWidth(LayoutParams.WRAP_CONTENT);
             p.setHeight(LayoutParams.WRAP_CONTENT);
             p.setBackgroundDrawable(null);
@@ -5708,12 +5784,28 @@
         }
     }
 
+    private EditText getTextFilterInput() {
+        if (mTextFilter == null) {
+            final LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+            mTextFilter = (EditText) layoutInflater.inflate(
+                    com.android.internal.R.layout.typing_filter, null);
+            // For some reason setting this as the "real" input type changes
+            // the text view in some way that it doesn't work, and I don't
+            // want to figure out why this is.
+            mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT
+                    | EditorInfo.TYPE_TEXT_VARIATION_FILTER);
+            mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+            mTextFilter.addTextChangedListener(this);
+        }
+        return mTextFilter;
+    }
+
     /**
      * Clear the text filter.
      */
     public void clearTextFilter() {
         if (mFiltered) {
-            mTextFilter.setText("");
+            getTextFilterInput().setText("");
             mFiltered = false;
             if (mPopup != null && mPopup.isShowing()) {
                 dismissPopup();
@@ -5759,7 +5851,8 @@
      */
     @Override
     public void onTextChanged(CharSequence s, int start, int before, int count) {
-        if (mPopup != null && isTextFilterEnabled()) {
+        if (isTextFilterEnabled()) {
+            createTextFilter(true);
             int length = s.length();
             boolean showing = mPopup.isShowing();
             if (!showing && length > 0) {
@@ -6331,6 +6424,7 @@
             }
             mFirstActivePosition = firstActivePosition;
 
+            //noinspection MismatchedReadAndWriteOfArray
             final View[] activeViews = mActiveViews;
             for (int i = 0; i < childCount; i++) {
                 View child = getChildAt(i);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index 13b6129..db6421e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -20,19 +20,15 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
-import android.os.Environment;
 import android.util.DisplayMetrics;
 import android.view.ContextMenu;
 import android.view.View;
-import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.TextView;
 
-import java.io.File;
-
 @SuppressWarnings({"UnusedDeclaration"})
 public class ListActivity extends Activity {
     private static final String[] DATA_LIST = {
@@ -86,7 +82,7 @@
 
         ListAdapter adapter = new SimpleListAdapter(this);
 
-        ListView list = (ListView) findViewById(R.id.list);
+        final ListView list = (ListView) findViewById(R.id.list);
         list.setAdapter(adapter);
         
         registerForContextMenu(list);