Merge "more targeted logging"
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index ca1effb..c773527 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -79,7 +79,7 @@
     /**
      * Map of the children of the {@link AdapterViewAnimator}.
      */
-    HashMap<Integer, ViewAndIndex> mViewsMap = new HashMap<Integer, ViewAndIndex>();
+    HashMap<Integer, ViewAndMetaData> mViewsMap = new HashMap<Integer, ViewAndMetaData>();
 
     /**
      * List of views pending removal from the {@link AdapterViewAnimator}
@@ -204,13 +204,18 @@
         mPreviousViews = new ArrayList<Integer>();
     }
 
-    class ViewAndIndex {
-        ViewAndIndex(View v, int i) {
-            view = v;
-            index = i;
-        }
+    class ViewAndMetaData {
         View view;
-        int index;
+        int relativeIndex;
+        int adapterPosition;
+        long itemId;
+
+        ViewAndMetaData(View view, int relativeIndex, int adapterPosition, long itemId) {
+            this.view = view;
+            this.relativeIndex = relativeIndex;
+            this.adapterPosition = adapterPosition;
+            this.itemId = itemId;
+        }
     }
 
     /**
@@ -376,6 +381,15 @@
         }
     }
 
+    private ViewAndMetaData getMetaDataForChild(View child) {
+        for (ViewAndMetaData vm: mViewsMap.values()) {
+            if (vm.view == child) {
+                return vm;
+            }
+        }
+        return null;
+     }
+
     LayoutParams createOrReuseLayoutParams(View v) {
         final ViewGroup.LayoutParams currentLp = v.getLayoutParams();
         if (currentLp instanceof ViewGroup.LayoutParams) {
@@ -478,7 +492,7 @@
 
             if (remove) {
                 View previousView = mViewsMap.get(index).view;
-                int oldRelativeIndex = mViewsMap.get(index).index;
+                int oldRelativeIndex = mViewsMap.get(index).relativeIndex;
 
                 mPreviousViews.add(index);
                 transformViewForTransition(oldRelativeIndex, -1, previousView, animate);
@@ -494,7 +508,7 @@
                 int index = modulo(i, getWindowSize());
                 int oldRelativeIndex;
                 if (mViewsMap.containsKey(index)) {
-                    oldRelativeIndex = mViewsMap.get(index).index;
+                    oldRelativeIndex = mViewsMap.get(index).relativeIndex;
                 } else {
                     oldRelativeIndex = -1;
                 }
@@ -507,14 +521,16 @@
 
                 if (inOldRange) {
                     View view = mViewsMap.get(index).view;
-                    mViewsMap.get(index).index = newRelativeIndex;
+                    mViewsMap.get(index).relativeIndex = newRelativeIndex;
                     applyTransformForChildAtIndex(view, newRelativeIndex);
                     transformViewForTransition(oldRelativeIndex, newRelativeIndex, view, animate);
 
                 // Otherwise this view is new to the window
                 } else {
                     // Get the new view from the adapter, add it and apply any transform / animation
-                    View newView = mAdapter.getView(modulo(i, adapterCount), null, this);
+                    final int adapterPosition = modulo(i, adapterCount);
+                    View newView = mAdapter.getView(adapterPosition, null, this);
+                    long itemId = mAdapter.getItemId(adapterPosition);
 
                     // We wrap the new view in a FrameLayout so as to respect the contract
                     // with the adapter, that is, that we don't modify this view directly
@@ -524,7 +540,8 @@
                     if (newView != null) {
                        fl.addView(newView);
                     }
-                    mViewsMap.put(index, new ViewAndIndex(fl, newRelativeIndex));
+                    mViewsMap.put(index, new ViewAndMetaData(fl, newRelativeIndex,
+                            adapterPosition, itemId));
                     addChild(fl);
                     applyTransformForChildAtIndex(fl, newRelativeIndex);
                     transformViewForTransition(-1, newRelativeIndex, fl, animate);
@@ -601,6 +618,7 @@
             case MotionEvent.ACTION_UP: {
                 if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) {
                     final View v = getCurrentView();
+                    final ViewAndMetaData viewData = getMetaDataForChild(v);
                     if (v != null) {
                         if (isTransformedTouchPointInView(ev.getX(), ev.getY(), v, null)) {
                             final Handler handler = getHandler();
@@ -613,7 +631,12 @@
                                     hideTapFeedback(v);
                                     post(new Runnable() {
                                         public void run() {
-                                            performItemClick(v, 0, 0);
+                                            if (viewData != null) {
+                                                performItemClick(v, viewData.adapterPosition,
+                                                        viewData.itemId);
+                                            } else {
+                                                performItemClick(v, 0, 0);
+                                            }
                                         }
                                     });
                                 }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index ec4ef4b..71c91e1 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -427,8 +427,8 @@
         // Here we need to make sure that the z-order of the children is correct
         for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
             int index = modulo(i, getWindowSize());
-            ViewAndIndex vi = mViewsMap.get(index);
-            if (vi != null) {
+            ViewAndMetaData vm = mViewsMap.get(index);
+            if (vm != null) {
                 View v = mViewsMap.get(index).view;
                 if (v != null) v.bringToFront();
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 2fd58e4..c5eaef9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -372,8 +372,6 @@
             if (mViewRoot == null) {
                 return ERROR_NOT_INFLATED.createResult();
             }
-            // measure the views
-            int w_spec, h_spec;
 
             RenderingMode renderingMode = params.getRenderingMode();
 
@@ -385,38 +383,64 @@
                 mMeasuredScreenHeight = params.getScreenHeight();
 
                 if (renderingMode != RenderingMode.NORMAL) {
-                    // measure the full size needed by the layout.
-                    w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth,
-                            renderingMode.isHorizExpand() ?
-                                    MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
-                                    : MeasureSpec.EXACTLY);
-                    h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight,
-                            renderingMode.isVertExpand() ?
-                                    MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
-                                    : MeasureSpec.EXACTLY);
-                    mViewRoot.measure(w_spec, h_spec);
+                    int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
+                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+                            : MeasureSpec.EXACTLY;
+                    int heightMeasureSpecMode = renderingMode.isVertExpand() ?
+                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+                            : MeasureSpec.EXACTLY;
 
+                    // We used to compare the measured size of the content to the screen size but
+                    // this does not work anymore due to the 2 following issues:
+                    // - If the content is in a decor (system bar, title/action bar), the root view
+                    //   will not resize even with the UNSPECIFIED because of the embedded layout.
+                    // - If there is no decor, but a dialog frame, then the dialog padding prevents
+                    //   comparing the size of the content to the screen frame (as it would not
+                    //   take into account the dialog padding).
+
+                    // The solution is to first get the content size in a normal rendering, inside
+                    // the decor or the dialog padding.
+                    // Then measure only the content with UNSPECIFIED to see the size difference
+                    // and apply this to the screen size.
+
+                    // first measure the full layout, with EXACTLY to get the size of the
+                    // content as it is inside the decor/dialog
+                    Pair<Integer, Integer> exactMeasure = measureView(
+                            mViewRoot, mContentRoot.getChildAt(0),
+                            mMeasuredScreenWidth, MeasureSpec.EXACTLY,
+                            mMeasuredScreenHeight, MeasureSpec.EXACTLY);
+
+                    // now measure the content only using UNSPECIFIED (where applicable, based on
+                    // the rendering mode). This will give us the size the content needs.
+                    Pair<Integer, Integer> result = measureView(
+                            mContentRoot, mContentRoot.getChildAt(0),
+                            mMeasuredScreenWidth, widthMeasureSpecMode,
+                            mMeasuredScreenHeight, heightMeasureSpecMode);
+
+                    // now look at the difference and add what is needed.
                     if (renderingMode.isHorizExpand()) {
-                        int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
-                        if (neededWidth > mMeasuredScreenWidth) {
-                            mMeasuredScreenWidth = neededWidth;
+                        int measuredWidth = exactMeasure.getFirst();
+                        int neededWidth = result.getFirst();
+                        if (neededWidth > measuredWidth) {
+                            mMeasuredScreenWidth += neededWidth - measuredWidth;
                         }
                     }
 
                     if (renderingMode.isVertExpand()) {
-                        int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
-                        if (neededHeight > mMeasuredScreenHeight) {
-                            mMeasuredScreenHeight = neededHeight;
+                        int measuredHeight = exactMeasure.getSecond();
+                        int neededHeight = result.getSecond();
+                        if (neededHeight > measuredHeight) {
+                            mMeasuredScreenHeight += neededHeight - measuredHeight;
                         }
                     }
                 }
             }
 
-            // remeasure with the size we need
+            // measure again with the size we need
             // This must always be done before the call to layout
-            w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY);
-            h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, MeasureSpec.EXACTLY);
-            mViewRoot.measure(w_spec, h_spec);
+            measureView(mViewRoot, null /*measuredView*/,
+                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
+                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
 
             // now do the layout.
             mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
@@ -494,6 +518,34 @@
     }
 
     /**
+     * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
+     * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
+     *
+     * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
+     * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
+     *
+     * @param viewToMeasure the view on which to execute measure().
+     * @param measuredView if non null, the view to query for its measured width/height.
+     * @param width the width to use in the MeasureSpec.
+     * @param widthMode the MeasureSpec mode to use for the width.
+     * @param height the height to use in the MeasureSpec.
+     * @param heightMode the MeasureSpec mode to use for the height.
+     * @return the measured width/height if measuredView is non-null, null otherwise.
+     */
+    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
+            int width, int widthMode, int height, int heightMode) {
+        int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
+        int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
+        viewToMeasure.measure(w_spec, h_spec);
+
+        if (measuredView != null) {
+            return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
+        }
+
+        return null;
+    }
+
+    /**
      * Animate an object
      * <p>
      * {@link #acquire(long)} must have been called before this.