OSDN Git Service

Fixes #1886237. Views drawing cache was not generated properly.
authorRomain Guy <romainguy@android.com>
Fri, 12 Jun 2009 00:35:47 +0000 (17:35 -0700)
committerRomain Guy <romainguy@android.com>
Fri, 12 Jun 2009 01:05:56 +0000 (18:05 -0700)
In compatibility mode, a View's drawing cache was created at the 160 density
scale instead of the right scale.

core/java/android/view/View.java
core/java/android/view/ViewGroup.java
core/java/android/view/ViewRoot.java

index bcb97ed..0497344 100644 (file)
@@ -75,17 +75,17 @@ import java.util.WeakHashMap;
  * This class represents the basic building block for user interface components. A View
  * occupies a rectangular area on the screen and is responsible for drawing and
  * event handling. View is the base class for <em>widgets</em>, which are
- * used to create interactive UI components (buttons, text fields, etc.). The 
+ * used to create interactive UI components (buttons, text fields, etc.). The
  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
  * are invisible containers that hold other Views (or other ViewGroups) and define
  * their layout properties.
  * </p>
  *
  * <div class="special">
- * <p>For an introduction to using this class to develop your 
- * application's user interface, read the Developer Guide documentation on 
+ * <p>For an introduction to using this class to develop your
+ * application's user interface, read the Developer Guide documentation on
  * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics
- * include: 
+ * include:
  * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>
  * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>
  * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a>
@@ -96,7 +96,7 @@ import java.util.WeakHashMap;
  * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>.
  * </p>
  * </div>
- * 
+ *
  * <a name="Using"></a>
  * <h3>Using Views</h3>
  * <p>
@@ -422,7 +422,7 @@ import java.util.WeakHashMap;
  * </p>
  *
  * <p>
- * Note that the framework will not draw views that are not in the invalid region. 
+ * Note that the framework will not draw views that are not in the invalid region.
  * </p>
  *
  * <p>
@@ -1830,7 +1830,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
         int viewFlagMasks = 0;
 
         boolean setScrollContainer = false;
-        
+
         int x = 0;
         int y = 0;
 
@@ -2464,7 +2464,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             if (!(parent instanceof View)) {
                 break;
             }
-            
+
             child = (View) parent;
             parent = child.getParent();
         }
@@ -2556,7 +2556,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * and previouslyFocusedRect provide insight into where the focus is coming from.
      * When overriding, be sure to call up through to the super class so that
      * the standard focus handling will occur.
-     * 
+     *
      * @param gainFocus True if the View has focus; false otherwise.
      * @param direction The direction focus has moved when requestFocus()
      *                  is called to give this view focus. Values are
@@ -2587,7 +2587,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                 && mAttachInfo.mHasWindowFocus) {
             imm.focusIn(this);
         }
-        
+
         invalidate();
         if (mOnFocusChangeListener != null) {
             mOnFocusChangeListener.onFocusChange(this, gainFocus);
@@ -2676,7 +2676,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * Subclasses of View overriding this method should always call super.onFocusLost().
      *
      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
-     * @see #onWindowFocusChanged(boolean) 
+     * @see #onWindowFocusChanged(boolean)
      *
      * @hide pending API council approval
      */
@@ -3578,14 +3578,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      */
     public void onStartTemporaryDetach() {
     }
-    
+
     /**
      * Called after {@link #onStartTemporaryDetach} when the container is done
      * changing the view.
      */
     public void onFinishTemporaryDetach() {
     }
-    
+
     /**
      * capture information of this view for later analysis: developement only
      * check dynamic switch to make sure we only dump view
@@ -3970,25 +3970,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * a call on that method would return a non-null InputConnection, and
      * they are really a first-class editor that the user would normally
      * start typing on when the go into a window containing your view.
-     * 
+     *
      * <p>The default implementation always returns false.  This does
      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
      * will not be called or the user can not otherwise perform edits on your
      * view; it is just a hint to the system that this is not the primary
      * purpose of this view.
-     * 
+     *
      * @return Returns true if this view is a text editor, else false.
      */
     public boolean onCheckIsTextEditor() {
         return false;
     }
-    
+
     /**
      * Create a new InputConnection for an InputMethod to interact
      * with the view.  The default implementation returns null, since it doesn't
      * support input methods.  You can override this to implement such support.
      * This is only needed for views that take focus and text input.
-     * 
+     *
      * <p>When implementing this, you probably also want to implement
      * {@link #onCheckIsTextEditor()} to indicate you will return a
      * non-null InputConnection.
@@ -4012,7 +4012,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     public boolean checkInputConnectionProxy(View view) {
         return false;
     }
-    
+
     /**
      * Show the context menu for this view. It is not safe to hold on to the
      * menu after returning from this method.
@@ -4743,7 +4743,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * whether an instance is opaque. Opaque Views are treated in a special way by
      * the View hierarchy, possibly allowing it to perform optimizations during
      * invalidate/draw passes.
-     * 
+     *
      * @return True if this View is guaranteed to be fully opaque, false otherwise.
      *
      * @hide Pending API council approval
@@ -5343,9 +5343,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             }
         }
     }
-    
+
     /**
-     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 
+     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
      * FastScroller is visible.
      * @return whether to temporarily hide the vertical scrollbar
      * @hide
@@ -5868,8 +5868,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                 EventLog.writeEvent(60002, hashCode());
             }
 
-            final int width = mRight - mLeft;
-            final int height = mBottom - mTop;
+            int width = mRight - mLeft;
+            int height = mBottom - mTop;
+
+            final AttachInfo attachInfo = mAttachInfo;
+            if (attachInfo != null) {
+                final boolean scalingRequired = attachInfo.mScalingRequired;
+                if (scalingRequired) {
+                    width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
+                    height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
+                }
+            }
 
             final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
             final boolean opaque = drawingCacheBackgroundColor != 0 ||
@@ -5925,11 +5934,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             }
 
             Canvas canvas;
-            final AttachInfo attachInfo = mAttachInfo;
             if (attachInfo != null) {
                 canvas = attachInfo.mCanvas;
                 if (canvas == null) {
                     canvas = new Canvas();
+
+                    // NOTE: This should have to happen only once since compatibility
+                    //       mode should not change at runtime
+                    if (attachInfo.mScalingRequired) {
+                        final float scale = attachInfo.mApplicationScale;
+                        canvas.scale(scale, scale);
+                    }
                 }
                 canvas.setBitmap(bitmap);
                 // Temporarily clobber the cached Canvas in case one of our children
@@ -6031,7 +6046,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             // Restore the cached Canvas for our siblings
             attachInfo.mCanvas = canvas;
         }
-        
+
         return bitmap;
     }
 
@@ -6971,7 +6986,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
         mUserPaddingBottom = bottom;
 
         final int viewFlags = mViewFlags;
-        
+
         // Common case is there are no scroll bars.
         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
             // TODO: Deal with RTL languages to adjust left padding instead of right.
@@ -6984,7 +6999,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                         ? 0 : getHorizontalScrollbarHeight();
             }
         }
-        
+
         if (mPaddingLeft != left) {
             changed = true;
             mPaddingLeft = left;
@@ -7121,7 +7136,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                 return v;
             }
         }
-        
+
         View parent = this;
 
         while (parent.mParent != null && parent.mParent instanceof View) {
@@ -7169,7 +7184,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             location[1] += view.mTop - view.mScrollY;
             viewParent = view.mParent;
         }
-        
+
         if (viewParent instanceof ViewRoot) {
             // *cough*
             final ViewRoot vr = (ViewRoot)viewParent;
@@ -7320,7 +7335,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * @return the Object stored in this view as a tag
      *
      * @see #setTag(int, Object)
-     * @see #getTag() 
+     * @see #getTag()
      */
     public Object getTag(int key) {
         SparseArray<Object> tags = null;
@@ -7376,7 +7391,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                     + "resource id.");
         }
 
-        setTagInternal(this, key, tag);        
+        setTagInternal(this, key, tag);
     }
 
     private static void setTagInternal(View view, int key, Object tag) {
@@ -7411,7 +7426,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     /**
      * Method that subclasses should implement to check their consistency. The type of
      * consistency check is indicated by the bit field passed as a parameter.
-     * 
+     *
      * @param consistency The type of consistency. See ViewDebug for more information.
      *
      * @throws IllegalStateException if the view is in an inconsistent state.
@@ -7966,7 +7981,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
 
     /**
      * BZZZTT!!1!
-     * 
+     *
      * <p>Provide haptic feedback to the user for this view.
      *
      * <p>The framework will provide haptic feedback for some built in actions,
@@ -7985,7 +8000,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
 
     /**
      * BZZZTT!!1!
-     * 
+     *
      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
      *
      * @param feedbackConstant One of the constants defined in
@@ -8448,11 +8463,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
          * The top view of the hierarchy.
          */
         View mRootView;
-        
+
         IBinder mPanelParentWindowToken;
         Surface mSurface;
 
         /**
+         * Scale factor used by the compatibility mode
+         */
+        float mApplicationScale;
+
+        /**
+         * Indicates whether the application is in compatibility mode
+         */
+        boolean mScalingRequired;
+
+        /**
          * Left position of this view's window
          */
         int mWindowLeft;
@@ -8639,18 +8664,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             // use use a height of 1, and then wack the matrix each time we
             // actually use it.
             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
-            
+
             paint.setShader(shader);
             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
         }
-        
+
         public void setFadeColor(int color) {
             if (color != 0 && color != mLastColor) {
                 mLastColor = color;
                 color |= 0xFF000000;
-                
+
                 shader = new LinearGradient(0, 0, 0, 1, color, 0, Shader.TileMode.CLAMP);
-                
+
                 paint.setShader(shader);
                 // Restore the default transfer mode (src_over)
                 paint.setXfermode(null);
index 8b0629c..af05501 100644 (file)
@@ -99,7 +99,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
 
     /**
      * Internal flags.
-     * 
+     *
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
@@ -152,7 +152,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
      * to get the index of the child to draw for that iteration.
      */
     protected static final int FLAG_USE_CHILD_DRAWING_ORDER = 0x400;
-    
+
     /**
      * When set, this ViewGroup supports static transformations on children; this causes
      * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be
@@ -161,7 +161,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
      * Any subclass overriding
      * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should
      * set this flags in {@link #mGroupFlags}.
-     * 
+     *
      * {@hide}
      */
     protected static final int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800;
@@ -222,7 +222,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
      * When set, this ViewGroup should not intercept touch events.
      */
     private static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
-    
+
     /**
      * Indicates which types of drawing caches are to be kept in memory.
      * This field should be made private, so it is hidden from the SDK.
@@ -698,7 +698,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
         ViewParent parent = mParent;
         if (parent != null) parent.recomputeViewAttributes(this);
     }
-    
+
     @Override
     void dispatchCollectViewAttributes(int visibility) {
         visibility |= mViewFlags&VISIBILITY_MASK;
@@ -830,16 +830,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                 }
             }
         }
-        
+
         boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
-                (action == MotionEvent.ACTION_CANCEL); 
+                (action == MotionEvent.ACTION_CANCEL);
 
         if (isUpOrCancel) {
             // Note, we've already copied the previous state to our local
             // variable, so this takes effect on the next event
             mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
         }
-        
+
         // The event wasn't an ACTION_DOWN, dispatch it to our target if
         // we have one.
         final View target = mMotionTarget;
@@ -886,18 +886,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
      * {@inheritDoc}
      */
     public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
-        
+
         if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {
             // We're already in this state, assume our ancestors are too
             return;
         }
-        
+
         if (disallowIntercept) {
             mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
         } else {
             mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
         }
-        
+
         // Pass it up to our parent
         if (mParent != null) {
             mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
@@ -1301,7 +1301,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             post(end);
         }
     }
-    
+
     /**
      * Returns the index of the child to draw for this iteration. Override this
      * if you want to change the drawing order of children. By default, it
@@ -1309,14 +1309,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
      * <p>
      * NOTE: In order for this method to be called, the
      * {@link #FLAG_USE_CHILD_DRAWING_ORDER} must be set.
-     * 
+     *
      * @param i The current iteration.
      * @return The index of the child to draw this iteration.
      */
     protected int getChildDrawingOrder(int childCount, int i) {
         return i;
     }
-    
+
     private void notifyAnimationListener() {
         mGroupFlags &= ~FLAG_NOTIFY_ANIMATION_LISTENER;
         mGroupFlags |= FLAG_ANIMATION_DONE;
@@ -1444,10 +1444,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
         final int sx = child.mScrollX;
         final int sy = child.mScrollY;
 
+        boolean scalingRequired = false;
         Bitmap cache = null;
         if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
                 (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
             cache = child.getDrawingCache();
+            scalingRequired = mAttachInfo.mScalingRequired;
         }
 
         final boolean hasNoCache = cache == null;
@@ -1457,6 +1459,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             canvas.translate(cl - sx, ct - sy);
         } else {
             canvas.translate(cl, ct);
+            if (scalingRequired) {
+                final float scale = 1.0f / mAttachInfo.mApplicationScale;
+                canvas.scale(scale, scale);
+            }
         }
 
         float alpha = 1.0f;
@@ -1499,7 +1505,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             if (hasNoCache) {
                 canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct));
             } else {
-                canvas.clipRect(0, 0, cr - cl, cb - ct);
+                if (!scalingRequired) {
+                    canvas.clipRect(0, 0, cr - cl, cb - ct);
+                } else {
+                    canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
+                }
             }
         }
 
@@ -1509,7 +1519,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                 if (ViewDebug.TRACE_HIERARCHY) {
                     ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
                 }
-                child.mPrivateFlags &= ~DIRTY_MASK;                
+                child.mPrivateFlags &= ~DIRTY_MASK;
                 child.dispatchDraw(canvas);
             } else {
                 child.draw(canvas);
@@ -1574,7 +1584,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             children[i].setSelected(selected);
         }
     }
-    
+
     @Override
     protected void dispatchSetPressed(boolean pressed) {
         final View[] children = mChildren;
@@ -1605,7 +1615,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
     /**
      * {@inheritDoc}
      *
-     * @see #setStaticTransformationsEnabled(boolean) 
+     * @see #setStaticTransformationsEnabled(boolean)
      */
     protected boolean getChildStaticTransformation(View child, Transformation t) {
         return false;
@@ -1872,10 +1882,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
         if (child.hasFocus()) {
             requestChildFocus(child, child.findFocus());
         }
-        
+
         AttachInfo ai = mAttachInfo;
         if (ai != null) {
-            boolean lastKeepOn = ai.mKeepScreenOn; 
+            boolean lastKeepOn = ai.mKeepScreenOn;
             ai.mKeepScreenOn = false;
             child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
             if (ai.mKeepScreenOn) {
@@ -2075,7 +2085,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
         }
 
         needGlobalAttributesUpdate(false);
-        
+
         removeFromArray(index);
 
         if (clearChildFocus) {
@@ -2108,7 +2118,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             }
 
             needGlobalAttributesUpdate(false);
-            
+
             if (notifyListener) {
                 onHierarchyChangeListener.onChildViewRemoved(this, view);
             }
@@ -2156,7 +2166,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
         View clearChildFocus = null;
 
         needGlobalAttributesUpdate(false);
-        
+
         for (int i = count - 1; i >= 0; i--) {
             final View view = children[i];
 
@@ -2201,7 +2211,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
         if (child == mFocused) {
             child.clearFocus();
         }
-        
+
         if (animate && child.getAnimation() != null) {
             addDisappearingView(child);
         } else if (child.mAttachInfo != null) {
@@ -3164,7 +3174,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             }
         }
     }
-    
+
 
     @Override
     protected boolean fitSystemWindows(Rect insets) {
@@ -3298,7 +3308,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
      * laid out. See
      * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
      * for a list of all child view attributes that this class supports.
-     * 
+     *
      * <p>
      * The base LayoutParams class just describes how big the view wants to be
      * for both width and height. For each dimension, it can specify one of:
@@ -3429,7 +3439,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
          * @param output the String to prepend to the internal representation
          * @return a String with the following format: output +
          *         "ViewGroup.LayoutParams={ width=WIDTH, height=HEIGHT }"
-         * 
+         *
          * @hide
          */
         public String debug(String output) {
@@ -3442,7 +3452,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
          *
          * @param size the size to convert
          * @return a String instance representing the supplied size
-         * 
+         *
          * @hide
          */
         protected static String sizeToString(int size) {
index ee8229d..d35b048 100644 (file)
@@ -94,18 +94,18 @@ public final class ViewRoot extends Handler implements ViewParent,
 
     static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();
 
-    private static int sDrawTime;    
+    private static int sDrawTime;
 
     long mLastTrackballTime = 0;
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
 
     final int[] mTmpLocation = new int[2];
-    
+
     final InputMethodCallback mInputMethodCallback;
     final SparseArray<Object> mPendingEvents = new SparseArray<Object>();
     int mPendingEventSeq = 0;
-    
+
     final Thread mThread;
 
     final WindowLeaked mLocation;
@@ -127,7 +127,7 @@ public final class ViewRoot extends Handler implements ViewParent,
     int mHeight;
     Rect mDirty; // will be a graphics.Region soon
     boolean mIsAnimating;
-    
+
     private CompatibilityInfo mCompatibilityInfo;
 
     final View.AttachInfo mAttachInfo;
@@ -170,7 +170,7 @@ public final class ViewRoot extends Handler implements ViewParent,
     int mScrollY;
     int mCurScrollY;
     Scroller mScroller;
-    
+
     EGL10 mEgl;
     EGLDisplay mEglDisplay;
     EGLContext mEglContext;
@@ -180,7 +180,7 @@ public final class ViewRoot extends Handler implements ViewParent,
     boolean mUseGL;
     boolean mGlWanted;
 
-    final ViewConfiguration mViewConfiguration;    
+    final ViewConfiguration mViewConfiguration;
 
     /**
      * see {@link #playSoundEffect(int)}
@@ -399,13 +399,15 @@ public final class ViewRoot extends Handler implements ViewParent,
                 mSoftInputMode = attrs.softInputMode;
                 mWindowAttributesChanged = true;
                 mAttachInfo.mRootView = view;
+                mAttachInfo.mScalingRequired = mCompatibilityInfo.mScalingRequired;
+                mAttachInfo.mApplicationScale = mCompatibilityInfo.mApplicationScale;
                 if (panelParentView != null) {
                     mAttachInfo.mPanelParentWindowToken
                             = panelParentView.getApplicationWindowToken();
                 }
                 mAdded = true;
                 int res; /* = WindowManagerImpl.ADD_OKAY; */
-                
+
                 // Schedule the first layout -before- adding to the window
                 // manager, to make sure we do the relayout before receiving
                 // any other events from the system.
@@ -594,7 +596,7 @@ public final class ViewRoot extends Handler implements ViewParent,
     int getHostVisibility() {
         return mAppVisible ? mView.getVisibility() : View.GONE;
     }
-    
+
     private void performTraversals() {
         // cache mView since it is used so much below...
         final View host = mView;
@@ -638,7 +640,7 @@ public final class ViewRoot extends Handler implements ViewParent,
             fullRedrawNeeded = true;
             mLayoutRequested = true;
 
-            DisplayMetrics packageMetrics = 
+            DisplayMetrics packageMetrics =
                 mView.getContext().getResources().getDisplayMetrics();
             desiredWindowWidth = packageMetrics.widthPixels;
             desiredWindowHeight = packageMetrics.heightPixels;
@@ -685,7 +687,7 @@ public final class ViewRoot extends Handler implements ViewParent,
         }
 
         boolean insetsChanged = false;
-        
+
         if (mLayoutRequested) {
             if (mFirst) {
                 host.fitSystemWindows(mAttachInfo.mContentInsets);
@@ -710,7 +712,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                         || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                     windowResizesToFitContent = true;
 
-                    DisplayMetrics packageMetrics = 
+                    DisplayMetrics packageMetrics =
                         mView.getContext().getResources().getDisplayMetrics();
                     desiredWindowWidth = packageMetrics.widthPixels;
                     desiredWindowHeight = packageMetrics.heightPixels;
@@ -770,7 +772,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                 }
             }
         }
-        
+
         if (params != null && (host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
             if (!PixelFormat.formatHasAlpha(params.format)) {
                 params.format = PixelFormat.TRANSLUCENT;
@@ -799,7 +801,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                 // computed insets.
                 insetsPending = computesInternalInsets
                         && (mFirst || viewVisibilityChanged);
-                
+
                 if (mWindowAttributes.memoryType == WindowManager.LayoutParams.MEMORY_TYPE_GPU) {
                     if (params == null) {
                         params = mWindowAttributes;
@@ -835,7 +837,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                         + " content=" + mPendingContentInsets.toShortString()
                         + " visible=" + mPendingVisibleInsets.toShortString()
                         + " surface=" + mSurface);
-                
+
                 contentInsetsChanged = !mPendingContentInsets.equals(
                         mAttachInfo.mContentInsets);
                 visibleInsetsChanged = !mPendingVisibleInsets.equals(
@@ -863,7 +865,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                         // all at once.
                         newSurface = true;
                         fullRedrawNeeded = true;
-    
+
                         if (mGlWanted && !mUseGL) {
                             initializeGL();
                             initialized = mGlCanvas != null;
@@ -908,7 +910,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                         + " mHeight=" + mHeight
                         + " measuredHeight" + host.mMeasuredHeight
                         + " coveredInsetsChanged=" + contentInsetsChanged);
-                
+
                  // Ask host how big it wants to be
                 host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
 
@@ -983,7 +985,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                         mTmpLocation[1] + host.mBottom - host.mTop);
 
                 host.gatherTransparentRegion(mTransparentRegion);
-                mTransparentRegion.scale(appScale);                
+                mTransparentRegion.scale(appScale);
                 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
@@ -1027,7 +1029,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                 }
             }
         }
-            
+
         if (mFirst) {
             // handle first focus request
             if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="
@@ -1065,7 +1067,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                 }
             }
         }
-        
+
         boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw();
 
         if (!cancelDraw && !newSurface) {
@@ -1153,7 +1155,7 @@ public final class ViewRoot extends Handler implements ViewParent,
             mAttachInfo.mViewScrollChanged = false;
             mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
         }
-        
+
         int yoff;
         final boolean scrolling = mScroller != null && mScroller.computeScrollOffset();
         if (scrolling) {
@@ -1318,7 +1320,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                     EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
                 }
             }
-            
+
         } finally {
             surface.unlockCanvasAndPost(canvas);
         }
@@ -1326,7 +1328,7 @@ public final class ViewRoot extends Handler implements ViewParent,
         if (LOCAL_LOGV) {
             Log.v("ViewRoot", "Surface " + surface + " unlockCanvasAndPost");
         }
-        
+
         if (scrolling) {
             mFullRedrawNeeded = true;
             scheduleTraversals();
@@ -1339,7 +1341,7 @@ public final class ViewRoot extends Handler implements ViewParent,
         final Rect vi = attachInfo.mVisibleInsets;
         int scrollY = 0;
         boolean handled = false;
-        
+
         if (vi.left > ci.left || vi.top > ci.top
                 || vi.right > ci.right || vi.bottom > ci.bottom) {
             // We'll assume that we aren't going to change the scroll
@@ -1426,7 +1428,7 @@ public final class ViewRoot extends Handler implements ViewParent,
                 }
             }
         }
-        
+
         if (scrollY != mScrollY) {
             if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Pan scroll changed: old="
                     + mScrollY + " , new=" + scrollY);
@@ -1440,10 +1442,10 @@ public final class ViewRoot extends Handler implements ViewParent,
             }
             mScrollY = scrollY;
         }
-        
+
         return handled;
     }
-    
+
     public void requestChildFocus(View child, View focused) {
         checkThread();
         if (mFocusedView != focused) {
@@ -1523,7 +1525,7 @@ public final class ViewRoot extends Handler implements ViewParent,
         } catch (RemoteException e) {
         }
     }
-    
+
     /**
      * Return true if child is an ancestor of parent, (or equal to the parent).
      */
@@ -1727,10 +1729,10 @@ public final class ViewRoot extends Handler implements ViewParent,
                         }
                     }
                 }
-                
+
                 mLastWasImTarget = WindowManager.LayoutParams
                         .mayUseInputMethod(mWindowAttributes.flags);
-                
+
                 InputMethodManager imm = InputMethodManager.peekInstance();
                 if (mView != null) {
                     if (hasWindowFocus && imm != null && mLastWasImTarget) {
@@ -2151,50 +2153,50 @@ public final class ViewRoot extends Handler implements ViewParent,
     }
 
     /**
-     * log motion events 
+     * log motion events
      */
     private static void captureMotionLog(String subTag, MotionEvent ev) {
-        //check dynamic switch        
+        //check dynamic switch
         if (ev == null ||
                 SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) {
             return;
-        } 
-        
-        StringBuilder sb = new StringBuilder(subTag + ": ");        
-        sb.append(ev.getDownTime()).append(',');        
-        sb.append(ev.getEventTime()).append(',');        
-        sb.append(ev.getAction()).append(',');        
-        sb.append(ev.getX()).append(',');        
-        sb.append(ev.getY()).append(',');        
-        sb.append(ev.getPressure()).append(',');        
-        sb.append(ev.getSize()).append(',');        
-        sb.append(ev.getMetaState()).append(',');        
-        sb.append(ev.getXPrecision()).append(',');        
-        sb.append(ev.getYPrecision()).append(',');        
-        sb.append(ev.getDeviceId()).append(',');        
+        }
+
+        StringBuilder sb = new StringBuilder(subTag + ": ");
+        sb.append(ev.getDownTime()).append(',');
+        sb.append(ev.getEventTime()).append(',');
+        sb.append(ev.getAction()).append(',');
+        sb.append(ev.getX()).append(',');
+        sb.append(ev.getY()).append(',');
+        sb.append(ev.getPressure()).append(',');
+        sb.append(ev.getSize()).append(',');
+        sb.append(ev.getMetaState()).append(',');
+        sb.append(ev.getXPrecision()).append(',');
+        sb.append(ev.getYPrecision()).append(',');
+        sb.append(ev.getDeviceId()).append(',');
         sb.append(ev.getEdgeFlags());
-        Log.d(TAG, sb.toString());        
+        Log.d(TAG, sb.toString());
     }
     /**
-     * log motion events 
+     * log motion events
      */
     private static void captureKeyLog(String subTag, KeyEvent ev) {
-        //check dynamic switch                
-        if (ev == null || 
+        //check dynamic switch
+        if (ev == null ||
                 SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) {
             return;
         }
-        StringBuilder sb = new StringBuilder(subTag + ": ");        
+        StringBuilder sb = new StringBuilder(subTag + ": ");
         sb.append(ev.getDownTime()).append(',');
         sb.append(ev.getEventTime()).append(',');
         sb.append(ev.getAction()).append(',');
-        sb.append(ev.getKeyCode()).append(',');        
+        sb.append(ev.getKeyCode()).append(',');
         sb.append(ev.getRepeatCount()).append(',');
         sb.append(ev.getMetaState()).append(',');
         sb.append(ev.getDeviceId()).append(',');
         sb.append(ev.getScanCode());
-        Log.d(TAG, sb.toString());        
-    }    
+        Log.d(TAG, sb.toString());
+    }
 
     int enqueuePendingEvent(Object event, boolean sendDone) {
         int seq = mPendingEventSeq+1;
@@ -2212,7 +2214,7 @@ public final class ViewRoot extends Handler implements ViewParent,
         }
         return event;
     }
-    
+
     private void deliverKeyEvent(KeyEvent event, boolean sendDone) {
         // If mView is null, we just consume the key event because it doesn't
         // make sense to do anything else with it.
@@ -2269,7 +2271,7 @@ public final class ViewRoot extends Handler implements ViewParent,
             }
         }
     }
-    
+
     private void deliverKeyEventToViewHierarchy(KeyEvent event, boolean sendDone) {
         try {
             if (mView != null && mAdded) {
@@ -2278,8 +2280,8 @@ public final class ViewRoot extends Handler implements ViewParent,
 
                 if (checkForLeavingTouchModeAndConsume(event)) {
                     return;
-                }                
-                
+                }
+
                 if (Config.LOGV) {
                     captureKeyLog("captureDispatchKeyEvent", event);
                 }
@@ -2384,12 +2386,12 @@ public final class ViewRoot extends Handler implements ViewParent,
         }
         return relayoutResult;
     }
-    
+
     /**
      * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT
      * with the default window size, and centers if the window wanted to fill
      * horizontally.
-     * 
+     *
      * @param attrs the window's layout params to adjust
      */
     private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) {
@@ -2628,14 +2630,14 @@ public final class ViewRoot extends Handler implements ViewParent,
             boolean immediate) {
         return scrollToRectOrFocus(rectangle, immediate);
     }
-    
+
     static class InputMethodCallback extends IInputMethodCallback.Stub {
         private WeakReference<ViewRoot> mViewRoot;
 
         public InputMethodCallback(ViewRoot viewRoot) {
             mViewRoot = new WeakReference<ViewRoot>(viewRoot);
         }
-        
+
         public void finishedEvent(int seq, boolean handled) {
             final ViewRoot viewRoot = mViewRoot.get();
             if (viewRoot != null) {
@@ -2647,13 +2649,13 @@ public final class ViewRoot extends Handler implements ViewParent,
             // Stub -- not for use in the client.
         }
     }
-    
+
     static class EventCompletion extends Handler {
         final IWindow mWindow;
         final KeyEvent mKeyEvent;
         final boolean mIsPointer;
         final MotionEvent mMotionEvent;
-        
+
         EventCompletion(Looper looper, IWindow window, KeyEvent key,
                 boolean isPointer, MotionEvent motion) {
             super(looper);
@@ -2663,7 +2665,7 @@ public final class ViewRoot extends Handler implements ViewParent,
             mMotionEvent = motion;
             sendEmptyMessage(0);
         }
-        
+
         @Override
         public void handleMessage(Message msg) {
             if (mKeyEvent != null) {
@@ -2705,7 +2707,7 @@ public final class ViewRoot extends Handler implements ViewParent,
             }
         }
     }
-    
+
     static class W extends IWindow.Stub {
         private final WeakReference<ViewRoot> mViewRoot;
         private final Looper mMainLooper;
@@ -2827,14 +2829,14 @@ public final class ViewRoot extends Handler implements ViewParent,
          * The maximum amount of acceleration we will apply.
          */
         static final float MAX_ACCELERATION = 20;
-        
+
         /**
          * The maximum amount of time (in milliseconds) between events in order
          * for us to consider the user to be doing fast trackball movements,
          * and thus apply an acceleration.
          */
         static final long FAST_MOVE_TIME = 150;
-        
+
         /**
          * Scaling factor to the time (in milliseconds) between events to how
          * much to multiple/divide the current acceleration.  When movement
@@ -2842,7 +2844,7 @@ public final class ViewRoot extends Handler implements ViewParent,
          * FAST_MOVE_TIME it divides it.
          */
         static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40);
-        
+
         float position;
         float absPosition;
         float acceleration = 1;
@@ -2894,7 +2896,7 @@ public final class ViewRoot extends Handler implements ViewParent,
             } else {
                 normTime = 0;
             }
-            
+
             // The number of milliseconds between each movement that is
             // considered "normal" and will not result in any acceleration
             // or deceleration, scaled by the offset we have here.
@@ -3052,7 +3054,7 @@ public final class ViewRoot extends Handler implements ViewParent,
         sRunQueues.set(rq);
         return rq;
     }
-    
+
     /**
      * @hide
      */