RenderSessionImpl.java revision 70114b33f8054cc38090a2bbd213ebf15abee63d
13bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/*
23bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
33bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *
43bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
53bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * you may not use this file except in compliance with the License.
63bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * You may obtain a copy of the License at
73bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *
83bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
93bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *
103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * See the License for the specific language governing permissions and
143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * limitations under the License.
153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */
163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetpackage com.android.layoutlib.bridge.impl;
183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
19ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
20ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
21ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
22ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
23ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
24ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
25ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet
267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding;
2764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig;
28ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener;
29ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser;
30ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback;
310d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources;
32ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession;
337062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference;
34ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue;
35ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result;
36ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status;
37d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams;
38b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode;
39d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo;
4070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport com.android.ide.common.rendering.api.ViewType;
413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.internal.util.XmlUtils;
4241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView;
4341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl;
4441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView;
4541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView;
4641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl;
4741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuView;
48ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
50ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
5264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.layoutlib.bridge.bars.NavigationBar;
5364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.layoutlib.bridge.bars.StatusBar;
54799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TitleBar;
558d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Guptaimport com.android.layoutlib.bridge.bars.ActionBarLayout;
567062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter;
577062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
5885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Guptaimport com.android.resources.Density;
591b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohetimport com.android.resources.ResourceType;
6064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.resources.ScreenOrientation;
61947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohetimport com.android.util.Pair;
623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
63799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException;
64799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
65994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.animation.AnimationThread;
6633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.Animator;
67ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport android.animation.AnimatorInflater;
6833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.LayoutTransition;
6962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener;
703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.app.Fragment_Delegate;
713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap;
723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap_Delegate;
733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Canvas;
743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.drawable.Drawable;
753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.DisplayMetrics;
763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.TypedValue;
77994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.AttachInfo_Accessor;
78994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.BridgeInflater;
7976f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.IWindowManager;
8064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport android.view.IWindowManagerImpl;
8176f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.Surface;
823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View;
833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View.MeasureSpec;
84d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.view.ViewGroup;
85ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport android.view.ViewGroup.LayoutParams;
866208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams;
8770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.view.ViewParent;
8876f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate;
897062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsListView;
907062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsSpinner;
9170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.widget.ActionMenuView;
927062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AdapterView;
937062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ExpandableListView;
943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.FrameLayout;
95f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.LinearLayout;
967062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ListView;
9762c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohetimport android.widget.QuickContactBadge;
983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.TabHost;
99f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.TabHost.TabSpec;
100d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.widget.TabWidget;
1013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1024c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohetimport java.awt.AlphaComposite;
1033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Color;
1043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Graphics2D;
1053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.image.BufferedImage;
1063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.ArrayList;
1073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.List;
1083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.Map;
1093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/**
111ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * Class implementing the render session.
112952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * <p/>
113ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming
114ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
1153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * be done on the layout.
1163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */
1170fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> {
1183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
1203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
1213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    // scene state
123ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private RenderSession mScene;
1243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BridgeXmlBlockParser mBlockParser;
1253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BridgeInflater mInflater;
1266a5b91fceb1913cab6416bef99d7b28530d16ecfXavier Ducrohet    private ResourceValue mWindowBackground;
127799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private ViewGroup mViewRoot;
128799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private FrameLayout mContentRoot;
1291392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private Canvas mCanvas;
1301392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private int mMeasuredScreenWidth = -1;
1311392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private int mMeasuredScreenHeight = -1;
132799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private boolean mIsAlphaChannelImage;
133799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private boolean mWindowIsFloating;
134a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
135a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private int mStatusBarSize;
13664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private int mNavigationBarSize;
13764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
138799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private int mTitleBarSize;
139799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private int mActionBarSize;
140a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    // information being returned through the API
1433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BufferedImage mImage;
144e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    private List<ViewInfo> mViewInfoList;
14585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private List<ViewInfo> mSystemViewInfoList;
1463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final class PostInflateException extends Exception {
1483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        private static final long serialVersionUID = 1L;
1493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        public PostInflateException(String message) {
1513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            super(message);
1523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
1533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
1543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
1563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Creates a layout scene with all the information coming from the layout bridge API.
1573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
1588d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
1598d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * which act as a
160ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * call to {@link RenderSessionImpl#acquire(long)}
1613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     *
1628d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * @see Bridge#createSession(SessionParams)
1633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
164b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohet    public RenderSessionImpl(SessionParams params) {
1650fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        super(new SessionParams(params));
166ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    }
167ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
168ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    /**
169ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
170ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * inflater, and parser.
171ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
172ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
173ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
174ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @return whether the scene was prepared
175ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
176ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @see #acquire(long)
177ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @see #release()
178ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     */
1790fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet    @Override
180ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result init(long timeout) {
1810fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        Result result = super.init(timeout);
182952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
183ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            return result;
184ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
1853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1860fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        SessionParams params = getParams();
1870fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
1883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
189835ad76e300033f1d9cccd214bd7d61d78d0240aDeepanshu Gupta
1900fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        RenderResources resources = getParams().getResources();
1910fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        DisplayMetrics metrics = getContext().getMetrics();
1923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
193a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // use default of true in case it's not found to use alpha by default
194a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        mIsAlphaChannelImage  = getBooleanThemeValue(resources,
195a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                "windowIsFloating", true /*defaultValue*/);
196a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
197799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating",
198799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                true /*defaultValue*/);
199ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
200a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        findBackground(resources);
201a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        findStatusBar(resources, metrics);
202799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        findActionBar(resources, metrics);
20364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        findNavigationBar(resources, metrics);
2043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
20576f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        // FIXME: find those out, and possibly add them to the render params
20676f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        boolean hasNavigationBar = true;
207952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        //noinspection ConstantConditions
20876f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
20976f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet                metrics, Surface.ROTATION_0,
2101e3c4a072f4476cedb958d75e2a6edf3bde8378fJohn Spurlock                hasNavigationBar);
21176f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
21276f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet
2133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // build the inflater and parser.
2140fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        mInflater = new BridgeInflater(context, params.getProjectCallback());
2150fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        context.setBridgeInflater(mInflater);
216ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
217a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        mBlockParser = new BridgeXmlBlockParser(
218a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet                params.getLayoutDescription(), context, false /* platformResourceFlag */);
219ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
2203054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet        return SUCCESS.createResult();
2213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
2223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
2233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
2243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Inflates the layout.
2253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
226ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
227ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
228ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
229ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #init(long)} was not called.
2303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
231ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result inflate() {
232ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
233ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
2343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        try {
2353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
2360fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            SessionParams params = getParams();
23764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
2380fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            BridgeContext context = getContext();
239510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta            boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
24085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
24164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
242cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet            // the view group that receives the window background.
243952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            ViewGroup backgroundView;
244cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
2450fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            if (mWindowIsFloating || params.isForceNoDecor()) {
246cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
24785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                mViewRoot.setLayoutDirection(layoutDirection);
248799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            } else {
24964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
25064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    /*
25164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                     * This is a special case where the navigation bar is on the right.
25264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+---+
25364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | Status bar (always)                             |   |
25464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+   |
25564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | (Layout with background drawable)               |   |
25664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
25764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | | Title/Action bar (optional)                 | |   |
25864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
25964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | | Content, vertical extending                 | |   |
26064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | |                                             | |   |
26164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
26264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+---+
26364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
26464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       So we create a horizontal layout, with the nav bar on the right,
26564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       and the left part is the normal layout below without the nav bar at
26664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       the bottom
26764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                     */
26864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    LinearLayout topLayout = new LinearLayout(context);
26985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    topLayout.setLayoutDirection(layoutDirection);
27064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mViewRoot = topLayout;
27164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    topLayout.setOrientation(LinearLayout.HORIZONTAL);
27264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
27364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    try {
27485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        NavigationBar navigationBar = createNavigationBar(context,
27585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
27664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        topLayout.addView(navigationBar);
277952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
27864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
27964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    }
28064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                }
28164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
282799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                /*
283799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 * we're creating the following layout
284799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 *
285799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
28664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                   | Status bar (always)                             |
287799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
288cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | (Layout with background drawable)               |
289cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
290cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | | Title/Action bar (optional)                 | |
291cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
292cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | | Content, vertical extending                 | |
293cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | |                                             | |
294cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
295799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
29664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                   | Navigation bar for soft buttons, maybe see above|
297799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
298799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
299799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 */
300799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
3010fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                LinearLayout topLayout = new LinearLayout(context);
302799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                topLayout.setOrientation(LinearLayout.VERTICAL);
30385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                topLayout.setLayoutDirection(layoutDirection);
30464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // if we don't already have a view root this is it
30564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (mViewRoot == null) {
30664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mViewRoot = topLayout;
30764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                } else {
30885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    int topLayoutWidth =
30985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
31064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
31185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            topLayoutWidth, LayoutParams.MATCH_PARENT);
31264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    topLayout.setLayoutParams(layoutParams);
31364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
31464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // this is the case of soft buttons + vertical bar.
31564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // this top layout is the first layout in the horizontal layout. see above)
316510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    if (isRtl && params.isRtlSupported()) {
317510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // If RTL is enabled, layoutlib will mirror the layouts. So, add the
318510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // topLayout to the right of Navigation Bar and layoutlib will draw it
319510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // to the left.
320510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        mViewRoot.addView(topLayout);
321510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    } else {
322510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // Add the top layout to the left of the Navigation Bar.
323510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        mViewRoot.addView(topLayout, 0);
324510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    }
32564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                }
326799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
327799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (mStatusBarSize > 0) {
328799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // system bar
329799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
33085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
33185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                                layoutDirection, params.isRtlSupported());
33285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        topLayout.addView(statusBar);
333952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
334799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
335799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
336799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
337799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
338cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                LinearLayout backgroundLayout = new LinearLayout(context);
339cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundView = backgroundLayout;
340cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundLayout.setOrientation(LinearLayout.VERTICAL);
341cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
342fa7ed38ae9c180ff12a7312e6ec740b5ba313a97Deepanshu Gupta                        LayoutParams.MATCH_PARENT, 0);
343cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                layoutParams.weight = 1;
344cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundLayout.setLayoutParams(layoutParams);
345cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                topLayout.addView(backgroundLayout);
346cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
347cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
348799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // if the theme says no title/action bar, then the size will be 0
349799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (mActionBarSize > 0) {
350952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    ActionBarLayout actionBar = createActionBar(context, params);
351952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    backgroundLayout.addView(actionBar);
352952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    actionBar.createMenuPopup();
353952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    mContentRoot = actionBar.getContentRoot();
354799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                } else if (mTitleBarSize > 0) {
355799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
35685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        TitleBar titleBar = createTitleBar(context,
35764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                                hardwareConfig.getDensity(), params.getAppLabel());
358cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                        backgroundLayout.addView(titleBar);
359952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
360799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
361799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
362799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
363799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
364799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // content frame
36585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                if (mContentRoot == null) {
36685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mContentRoot = new FrameLayout(context);
36785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    layoutParams = new LinearLayout.LayoutParams(
36885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            LayoutParams.MATCH_PARENT, 0);
36985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    layoutParams.weight = 1;
37085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mContentRoot.setLayoutParams(layoutParams);
37185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    backgroundLayout.addView(mContentRoot);
37285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                }
373799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
37464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
37564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        mNavigationBarSize > 0) {
376799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // system bar
377799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
37885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        NavigationBar navigationBar = createNavigationBar(context,
37985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
38064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        topLayout.addView(navigationBar);
381952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
382799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
383799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
384799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
385799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            }
386799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
3873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
3883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // Sets the project callback (custom view loader) to the fragment delegate so that
3893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // it can instantiate the custom Fragment.
3900fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            Fragment_Delegate.setProjectCallback(params.getProjectCallback());
3913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
392799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            View view = mInflater.inflate(mBlockParser, mContentRoot);
3933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
3947062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // done with the parser, pop it.
3957062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            context.popParser();
3967062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
3973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Fragment_Delegate.setProjectCallback(null);
3983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
3993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // set the AttachInfo on the root view.
400994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet            AttachInfo_Accessor.setAttachInfo(mViewRoot);
4013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
402a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet            // post-inflate process. For now this supports TabHost/TabWidget
4030fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            postInflateProcess(view, params.getProjectCallback());
404a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet
4053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the background drawable
406952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            if (mWindowBackground != null) {
4070fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
40864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                backgroundView.setBackground(d);
4093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
411ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
4123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (PostInflateException e) {
413ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_INFLATION.createResult(e.getMessage(), e);
4143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (Throwable e) {
4153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the real cause of the exception.
4163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Throwable t = e;
4173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            while (t.getCause() != null) {
4183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                t = t.getCause();
4193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
421ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_INFLATION.createResult(t.getMessage(), t);
4223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
4233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
4243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
4263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Renders the scene.
4273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
428ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
429ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
4304c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     * @param freshRender whether the render is a new one and should erase the existing bitmap (in
4314c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *      the case where bitmaps are reused). This is typically needed when not playing
4324c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *      animations.)
4334c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *
434ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
435ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
4361392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet     *
4378d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * @see SessionParams#getRenderingMode()
438799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#render(long)
4393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
4404c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet    public Result render(boolean freshRender) {
441ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
442ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
4430fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        SessionParams params = getParams();
4440fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
4453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        try {
4463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (mViewRoot == null) {
447ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                return ERROR_NOT_INFLATED.createResult();
4483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4500fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            RenderingMode renderingMode = params.getRenderingMode();
45164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
452e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet
4531392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            // only do the screen measure when needed.
4541392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            boolean newRenderSize = false;
4551392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            if (mMeasuredScreenWidth == -1) {
4561392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                newRenderSize = true;
45764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
45864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
4591392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
4601392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                if (renderingMode != RenderingMode.NORMAL) {
4618ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
4628ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
4638ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            : MeasureSpec.EXACTLY;
4648ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    int heightMeasureSpecMode = renderingMode.isVertExpand() ?
4658ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
4668ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            : MeasureSpec.EXACTLY;
4678ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4688ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // We used to compare the measured size of the content to the screen size but
4698ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // this does not work anymore due to the 2 following issues:
4708ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // - If the content is in a decor (system bar, title/action bar), the root view
4718ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   will not resize even with the UNSPECIFIED because of the embedded layout.
4728ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // - If there is no decor, but a dialog frame, then the dialog padding prevents
4738ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   comparing the size of the content to the screen frame (as it would not
4748ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   take into account the dialog padding).
4758ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4768ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // The solution is to first get the content size in a normal rendering, inside
4778ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // the decor or the dialog padding.
4788ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // Then measure only the content with UNSPECIFIED to see the size difference
4798ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // and apply this to the screen size.
4808ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4818ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // first measure the full layout, with EXACTLY to get the size of the
4828ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // content as it is inside the decor/dialog
483952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    @SuppressWarnings("deprecation")
4848ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    Pair<Integer, Integer> exactMeasure = measureView(
4858ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mViewRoot, mContentRoot.getChildAt(0),
4868ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth, MeasureSpec.EXACTLY,
4878ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight, MeasureSpec.EXACTLY);
4888ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4898ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // now measure the content only using UNSPECIFIED (where applicable, based on
4908ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // the rendering mode). This will give us the size the content needs.
491952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    @SuppressWarnings("deprecation")
4928ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    Pair<Integer, Integer> result = measureView(
4938ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mContentRoot, mContentRoot.getChildAt(0),
4948ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth, widthMeasureSpecMode,
4958ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight, heightMeasureSpecMode);
4968ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4978ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // now look at the difference and add what is needed.
4981392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    if (renderingMode.isHorizExpand()) {
4998ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int measuredWidth = exactMeasure.getFirst();
5008ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int neededWidth = result.getFirst();
5018ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        if (neededWidth > measuredWidth) {
5028ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth += neededWidth - measuredWidth;
5031392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                        }
504e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet                    }
5053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5061392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    if (renderingMode.isVertExpand()) {
5078ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int measuredHeight = exactMeasure.getSecond();
5088ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int neededHeight = result.getSecond();
5098ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        if (neededHeight > measuredHeight) {
5108ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight += neededHeight - measuredHeight;
5111392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                        }
512e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet                    }
5133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
5143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
5153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5168ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            // measure again with the size we need
5173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // This must always be done before the call to layout
5188ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            measureView(mViewRoot, null /*measuredView*/,
5198ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
5208ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
5213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // now do the layout.
523a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
5243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
525f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet            if (params.isLayoutOnly()) {
526f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // delete the canvas and image to reset them on the next full rendering
527f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mImage = null;
528f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mCanvas = null;
529f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet            } else {
530994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet                AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
531f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
532f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // draw the views
533f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // create the BufferedImage into which the layout will be rendered.
534f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                boolean newImage = false;
535f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                if (newRenderSize || mCanvas == null) {
536f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    if (params.getImageFactory() != null) {
537f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        mImage = params.getImageFactory().getImage(
538f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenWidth,
539f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenHeight);
540f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    } else {
541f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        mImage = new BufferedImage(
542f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenWidth,
543f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenHeight,
544f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                BufferedImage.TYPE_INT_ARGB);
545f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        newImage = true;
546f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    }
547f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
548f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    if (params.isBgColorOverridden()) {
549f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        // since we override the content, it's the same as if it was a new image.
550f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        newImage = true;
551f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        Graphics2D gc = mImage.createGraphics();
552f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.setColor(new Color(params.getOverrideBgColor(), true));
553f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.setComposite(AlphaComposite.Src);
554f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
555f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.dispose();
556f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    }
557f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
558f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    // create an Android bitmap around the BufferedImage
559f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
56064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                            true /*isMutable*/, hardwareConfig.getDensity());
561f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
562f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    // create a Canvas around the Android bitmap
563f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    mCanvas = new Canvas(bitmap);
56464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
5651392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                }
5663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
567952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                if (freshRender && !newImage) {
5681392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    Graphics2D gc = mImage.createGraphics();
5694c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet                    gc.setComposite(AlphaComposite.Src);
5703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
571f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.setColor(new Color(0x00000000, true));
572f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.fillRect(0, 0,
573f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                            mMeasuredScreenWidth, mMeasuredScreenHeight);
574a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
575f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    // done
576f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.dispose();
577f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                }
578a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
579f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mViewRoot.draw(mCanvas);
5804c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet            }
5814c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet
58241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
58341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta                    false);
5843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // success!
586ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
5873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (Throwable e) {
5883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the real cause of the exception.
5893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Throwable t = e;
5903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            while (t.getCause() != null) {
5913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                t = t.getCause();
5923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
5933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
594ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_UNKNOWN.createResult(t.getMessage(), t);
5953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
5963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
5973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
5998ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
6008ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
6018ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     *
6028ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
6038ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
6048ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     *
6058ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param viewToMeasure the view on which to execute measure().
6068ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param measuredView if non null, the view to query for its measured width/height.
6078ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param width the width to use in the MeasureSpec.
6088ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param widthMode the MeasureSpec mode to use for the width.
6098ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param height the height to use in the MeasureSpec.
6108ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param heightMode the MeasureSpec mode to use for the height.
6118ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @return the measured width/height if measuredView is non-null, null otherwise.
6128ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     */
613952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
6148ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
6158ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            int width, int widthMode, int height, int heightMode) {
6168ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
6178ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
6188ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        viewToMeasure.measure(w_spec, h_spec);
6198ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6208ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        if (measuredView != null) {
6218ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
6228ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        }
6238ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6248ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        return null;
6258ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    }
6268ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6278ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    /**
628ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * Animate an object
629ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * <p>
630ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
631ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
632ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
633ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
63433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
635799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
636ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     */
637ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result animate(Object targetObject, String animationName,
638ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            boolean isFrameworkAnimation, IAnimationListener listener) {
639ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
640ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
6410fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
6420fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
643ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        // find the animation file.
644952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        ResourceValue animationResource;
645ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        int animationId = 0;
646ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        if (isFrameworkAnimation) {
6470fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            animationResource = context.getRenderResources().getFrameworkResource(
6481b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
649ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            if (animationResource != null) {
650947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
651ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
652ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        } else {
6530fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            animationResource = context.getRenderResources().getProjectResource(
6541b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
655ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            if (animationResource != null) {
6560fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                animationId = context.getProjectCallback().getResourceId(
6571b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                        ResourceType.ANIMATOR, animationName);
658ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
659ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
660ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
661ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        if (animationResource != null) {
662ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            try {
6630fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                Animator anim = AnimatorInflater.loadAnimator(context, animationId);
664ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                if (anim != null) {
665ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                    anim.setTarget(targetObject);
666ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
66733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    new PlayAnimationThread(anim, this, animationName, listener).start();
668ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
669ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                    return SUCCESS.createResult();
670ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                }
671ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            } catch (Exception e) {
672b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                // get the real cause of the exception.
673b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                Throwable t = e;
674b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                while (t.getCause() != null) {
675b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                    t = t.getCause();
676b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                }
677b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
678ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                return ERROR_UNKNOWN.createResult(t.getMessage(), t);
679ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
680ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
681ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
682ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        return ERROR_ANIM_NOT_FOUND.createResult();
683b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
684b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
68533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
68633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Insert a new child into an existing parent.
68733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
68833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
68933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
69033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
69133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
69233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
693799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
69433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
695ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
69633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            final int index, IAnimationListener listener) {
697b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        checkLock();
698b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
6990fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
7000fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
701b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // create a block parser for the XML
702a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
703a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet                childXml, context, false /* platformResourceFlag */);
704b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
705b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // inflate the child without adding it to the root since we want to control where it'll
706b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // get added. We do pass the parentView however to ensure that the layoutParams will
707b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // be created correctly.
70833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
709a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        blockParser.ensurePopped();
710b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
71133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        invalidateRenderingSize();
71233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
71333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
71433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            new AnimationThread(this, "insertChild", listener) {
71533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
71633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
717ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                public Result preAnimation() {
71833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parentView.setLayoutTransition(new LayoutTransition());
71933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    return addView(parentView, child, index);
72033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
72133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
72233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
72333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                public void postAnimation() {
72433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parentView.setLayoutTransition(null);
72533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
72633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            }.start();
72733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
72833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
729ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult(child);
7301392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        }
7311392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
73233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        // add it to the parentView in the correct location
733ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        Result result = addView(parentView, child, index);
734952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
73533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
73633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
737b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
7384c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        result = render(false /*freshRender*/);
7391766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        if (result.isSuccess()) {
74033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            result = result.getCopyWithData(child);
7411766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        }
7421766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet
7431766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        return result;
744b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
745b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
74633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
74733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Adds a given view to a given parent at a given index.
74833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
74933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param parent the parent to receive the view
75033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param view the view to add to the parent
75133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param index the index where to do the add.
75233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
753ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
754ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
75533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
75633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
757ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private Result addView(ViewGroup parent, View view, int index) {
75833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        try {
75933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            parent.addView(view, index);
760ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
76133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        } catch (UnsupportedOperationException e) {
76233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
763ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
76433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
76533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
76633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
76733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
76833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Moves a view to a new parent at a given location
76933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
77033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
77133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
77233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
77333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
77433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
775799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
77633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
77762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet    public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
77824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
779b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        checkLock();
780b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
78133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        invalidateRenderingSize();
78233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
783ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        LayoutParams layoutParams = null;
78433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (layoutParamsMap != null) {
78533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // need to create a new LayoutParams object for the new parent.
78662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            layoutParams = newParentView.generateLayoutParams(
78733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
78833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
7891392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
79062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        // get the current parent of the view that needs to be moved.
79162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        final ViewGroup previousParent = (ViewGroup) childView.getParent();
79262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
79333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
79433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            final LayoutParams params = layoutParams;
795ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
79624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            // there is no support for animating views across layouts, so in case the new and old
79724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            // parent views are different we fake the animation through a no animation thread.
79824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            if (previousParent != newParentView) {
79924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                new Thread("not animated moveChild") {
80024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
80124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public void run() {
80224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        Result result = moveView(previousParent, newParentView, childView, index,
80324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                params);
804952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        if (!result.isSuccess()) {
80524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            listener.done(result);
80624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
80724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
80824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // ready to do the work, acquire the scene.
80924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        result = acquire(250);
810952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        if (!result.isSuccess()) {
81124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            listener.done(result);
81224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            return;
81324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
81424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
81524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        try {
8164c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet                            result = render(false /*freshRender*/);
81724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            if (result.isSuccess()) {
81824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                listener.onNewFrame(RenderSessionImpl.this.getSession());
81924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            }
82024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        } finally {
82124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            release();
82224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
82324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
82424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        listener.done(result);
82562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
82624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                }.start();
82724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            } else {
82824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                new AnimationThread(this, "moveChild", listener) {
82962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
83024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
83124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public Result preAnimation() {
83224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // set up the transition for the parent.
83324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        LayoutTransition transition = new LayoutTransition();
83424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        previousParent.setLayoutTransition(transition);
8355562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet
83624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // tweak the animation durations and start delays (to match the duration of
83724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // animation playing just before).
83824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // Note: Cannot user Animation.setDuration() directly. Have to set it
83924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // on the LayoutTransition.
84024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
84124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // CHANGE_DISAPPEARING plays after DISAPPEARING
84224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
843ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
84424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
84524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
84624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
84724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // CHANGE_APPEARING plays after CHANGE_APPEARING
84824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
84924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
85024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.APPEARING, 100);
85124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
85224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        return moveView(previousParent, newParentView, childView, index, params);
85324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    }
85424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
85524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
85624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public void postAnimation() {
85724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        previousParent.setLayoutTransition(null);
85824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        newParentView.setLayoutTransition(null);
85924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    }
86024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                }.start();
86124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            }
86233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
86333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
864ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult(layoutParams);
865b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        }
866b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
86762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
868952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
86933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
87033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
871b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
8724c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        result = render(false /*freshRender*/);
873ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        if (layoutParams != null && result.isSuccess()) {
87433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            result = result.getCopyWithData(layoutParams);
875ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        }
876ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
877ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        return result;
878b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
879b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
88033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
88133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Moves a View from its current parent to a new given parent at a new given location, with
88233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * an optional new {@link LayoutParams} instance
88333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
88462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet     * @param previousParent the previous parent, still owning the child at the time of the call.
88562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet     * @param newParent the new parent
88624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet     * @param movedView the view to move
88733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param index the new location in the new parent
88833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param params an option (can be null) {@link LayoutParams} instance.
88933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
890ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
891ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
89233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
89333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
89424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
89524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            final View movedView, final int index, final LayoutParams params) {
8961392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        try {
89762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            // check if there is a transition on the previousParent.
89824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            LayoutTransition previousTransition = previousParent.getLayoutTransition();
89924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            if (previousTransition != null) {
9005562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // in this case there is an animation. This means we have to wait for the child's
9015562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // parent reference to be null'ed out so that we can add it to the new parent.
9025562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // It is technically removed right before the DISAPPEARING animation is done (if
9035562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // the animation of this type is not null, otherwise it's after which is impossible
9045562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // to handle).
9055562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // Because there is no move animation, if the new parent is the same as the old
9065562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
9075562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // adding the child or the child will appear in its new location before the
9085562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // other children have made room for it.
90962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
91062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // add a listener to the transition to be notified of the actual removal.
91124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousTransition.addTransitionListener(new TransitionListener() {
91224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    private int mChangeDisappearingCount = 0;
91362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
914d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                    @Override
91562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    public void startTransition(LayoutTransition transition, ViewGroup container,
91662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            View view, int transitionType) {
91724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
91824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            mChangeDisappearingCount++;
91924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
92062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
92133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
922d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                    @Override
92362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    public void endTransition(LayoutTransition transition, ViewGroup container,
92462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            View view, int transitionType) {
92524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
92624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            mChangeDisappearingCount--;
92724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
92824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
92924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
93024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                mChangeDisappearingCount == 0) {
93162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            // add it to the parentView in the correct location
93262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            if (params != null) {
93324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                newParent.addView(movedView, index, params);
93462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            } else {
93524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                newParent.addView(movedView, index);
93662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            }
93762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                        }
93862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
93962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                });
94062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
94162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // remove the view from the current parent.
94224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousParent.removeView(movedView);
94362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
94462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // and return since adding the view to the new parent is done in the listener.
94562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                return SUCCESS.createResult();
94633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            } else {
94762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // standard code with no animation. pretty simple.
94824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousParent.removeView(movedView);
94933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
95062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // add it to the parentView in the correct location
95162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                if (params != null) {
95224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    newParent.addView(movedView, index, params);
95362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                } else {
95424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    newParent.addView(movedView, index);
95562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                }
95662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
95762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                return SUCCESS.createResult();
95862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            }
9591392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        } catch (UnsupportedOperationException e) {
9601392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
961ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
962b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        }
96333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
96433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
96533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
96633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Removes a child from its current parent.
96733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
96833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
96933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
97033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
97133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
97233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
973799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#removeChild(Object, IAnimationListener)
97433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
975ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result removeChild(final View childView, IAnimationListener listener) {
97633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        checkLock();
977b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
9781392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        invalidateRenderingSize();
9791392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
98033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        final ViewGroup parent = (ViewGroup) childView.getParent();
98133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
98233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
98333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            new AnimationThread(this, "moveChild", listener) {
98433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
98533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
986ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                public Result preAnimation() {
98733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parent.setLayoutTransition(new LayoutTransition());
98833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    return removeView(parent, childView);
98933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
99033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
99133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
99233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                public void postAnimation() {
99333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parent.setLayoutTransition(null);
99433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
99533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            }.start();
99633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
99733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
998ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
99933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
100033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
1001ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        Result result = removeView(parent, childView);
1002952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
100333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
100433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
100533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
10064c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        return render(false /*freshRender*/);
1007ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    }
1008ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
1009ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    /**
101033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Removes a given view from its current parent.
101133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
101233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param view the view to remove from its parent
101333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
1014ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
1015ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
101633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
101733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
1018ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private Result removeView(ViewGroup parent, View view) {
101933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        try {
102033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            parent.removeView(view);
1021ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
102233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        } catch (UnsupportedOperationException e) {
102333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
1024ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
102533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
102633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
102733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
1028ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
1029a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private void findBackground(RenderResources resources) {
1030952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!getParams().isBgColorOverridden()) {
103141fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet            mWindowBackground = resources.findItemInTheme("windowBackground",
103241fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                    true /*isFrameworkAttr*/);
1033a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            if (mWindowBackground != null) {
1034a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                mWindowBackground = resources.resolveResValue(mWindowBackground);
1035a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1036a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1037a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
10383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
103964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private boolean hasSoftwareButtons() {
104064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        return getParams().getHardwareConfig().hasSoftwareButtons();
1041a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
10423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1043a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
104464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        boolean windowFullscreen = getBooleanThemeValue(resources,
104564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                "windowFullscreen", false /*defaultValue*/);
1046a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1047952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!windowFullscreen && !mWindowIsFloating) {
104864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            // default value
104964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
1050a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
105164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            // get the real value
105264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
105364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    "status_bar_height");
1054a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
105564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (value != null) {
105664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
105764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        value.getValue(), true /*requireUnit*/);
105864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (typedValue != null) {
105964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // compute the pixel value based on the display metrics
106064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mStatusBarSize = (int)typedValue.getDimension(metrics);
1061a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                }
1062a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1063a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1064a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1065a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1066799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
1067799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        if (mWindowIsFloating) {
1068799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            return;
1069a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1070a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1071a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        boolean windowActionBar = getBooleanThemeValue(resources,
1072a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                "windowActionBar", true /*defaultValue*/);
1073a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1074a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // if there's a value and it's false (default is true)
1075a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        if (windowActionBar) {
10763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
10773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // default size of the window title bar
1078799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
10793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
10803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get value from the theme.
108141fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet            ResourceValue value = resources.findItemInTheme("actionBarSize",
108241fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                    true /*isFrameworkAttr*/);
10833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
10843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // resolve it
1085a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            value = resources.resolveResValue(value);
10863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
10873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (value != null) {
10883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                // get the numerical value, if available
1089d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
1090d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                        true /*requireUnit*/);
10913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                if (typedValue != null) {
10923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    // compute the pixel value based on the display metrics
1093799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    mActionBarSize = (int)typedValue.getDimension(metrics);
10943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
10953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
1096799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        } else {
1097799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            // action bar overrides title bar so only look for this one if action bar is hidden
1098799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            boolean windowNoTitle = getBooleanThemeValue(resources,
1099799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    "windowNoTitle", false /*defaultValue*/);
11003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1101952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            if (!windowNoTitle) {
1102a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1103799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // default size of the window title bar
1104799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
1105a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1106799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // get value from the theme.
110741fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                ResourceValue value = resources.findItemInTheme("windowTitleSize",
110841fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                        true /*isFrameworkAttr*/);
1109a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1110799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // resolve it
1111799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                value = resources.resolveResValue(value);
11123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1113799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (value != null) {
1114799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // get the numerical value, if available
1115d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                    TypedValue typedValue = ResourceHelper.getValue("windowTitleSize",
1116d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                            value.getValue(), true /*requireUnit*/);
1117799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    if (typedValue != null) {
1118799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                        // compute the pixel value based on the display metrics
1119799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                        mTitleBarSize = (int)typedValue.getDimension(metrics);
1120799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
1121a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                }
1122a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1123799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
1124a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1125a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1126a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
112764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
1128952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (hasSoftwareButtons() && !mWindowIsFloating) {
11293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // default value
113164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            mNavigationBarSize = 48; // ??
113264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
113364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = getParams().getHardwareConfig();
113464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
113564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            boolean barOnBottom = true;
113664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
113764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
113864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // compute the dp of the screen.
113964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                int shortSize = hardwareConfig.getScreenHeight();
114064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
114164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // compute in dp
1142952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /
1143952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        hardwareConfig.getDensity().getDpiValue();
114464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
1145952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                // 0-599dp: "phone" UI with bar on the side
1146952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                // 600+dp: "tablet" UI with bar on the bottom
1147952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                barOnBottom = shortSizeDp >= 600;
114864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            }
114964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
115064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (barOnBottom) {
115164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mNavigationBarOrientation = LinearLayout.HORIZONTAL;
115264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            } else {
115364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mNavigationBarOrientation = LinearLayout.VERTICAL;
115464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            }
11553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1156089143ffed72bb47fd8d870f29caffb646138781Xavier Ducrohet            // get the real value
11571b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
115864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
1159a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
11603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (value != null) {
116164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
1162d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
11633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                if (typedValue != null) {
11643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    // compute the pixel value based on the display metrics
116564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mNavigationBarSize = (int)typedValue.getDimension(metrics);
11663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
11673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
1168a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1169a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1170a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
117141fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet    /**
117241fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * Looks for a attribute in the current theme. The attribute is in the android
117341fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * namespace.
117441fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     *
117541fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param resources the render resources
117641fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param name the name of the attribute
117741fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param defaultValue the default value.
117841fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @return the value of the attribute or the default one if not found.
117941fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     */
1180a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private boolean getBooleanThemeValue(RenderResources resources,
1181a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            String name, boolean defaultValue) {
1182a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1183a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // get the title bar flag from the current theme.
118441fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet        ResourceValue value = resources.findItemInTheme(name, true /*isFrameworkAttr*/);
1185a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1186a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // because it may reference something else, we resolve it.
1187a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        value = resources.resolveResValue(value);
11883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1189a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // if there's no value, return the default.
1190a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        if (value == null || value.getValue() == null) {
1191a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            return defaultValue;
11923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
11933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1194a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
11953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
11963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
1198952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * Post process on a view hierarchy that was just inflated.
1199952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * <p/>
1200952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the
12013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
12023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * based on the content of the {@link FrameLayout}.
12033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param view the root view to process.
12043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param projectCallback callback to the project.
12053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
1206952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
12073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private void postInflateProcess(View view, IProjectCallback projectCallback)
12083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throws PostInflateException {
12093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (view instanceof TabHost) {
12103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            setupTabHost((TabHost)view, projectCallback);
121162c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet        } else if (view instanceof QuickContactBadge) {
121262c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet            QuickContactBadge badge = (QuickContactBadge) view;
121362c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet            badge.setImageToDefault();
12147062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet        } else if (view instanceof AdapterView<?>) {
12157062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // get the view ID.
12167062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            int id = view.getId();
12177062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12187062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            BridgeContext context = getContext();
12197062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12207062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // get a ResourceReference from the integer ID.
12217062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            ResourceReference listRef = context.resolveId(id);
12227062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12237062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            if (listRef != null) {
12247062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                SessionParams params = getParams();
12257062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                AdapterBinding binding = params.getAdapterBindings().get(listRef);
12267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12277062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                // if there was no adapter binding, trying to get it from the call back.
12287062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                if (binding == null) {
12297062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    binding = params.getProjectCallback().getAdapterBinding(listRef,
12307062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            context.getViewKey(view), view);
12317062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                }
12327062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12337062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                if (binding != null) {
12347062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12357062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    if (view instanceof AbsListView) {
12367062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) &&
12377062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                view instanceof ListView) {
12387062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ListView list = (ListView) view;
12397062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12407062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            boolean skipCallbackParser = false;
12417062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12427062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            int count = binding.getHeaderCount();
12437062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            for (int i = 0 ; i < count ; i++) {
12447062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
12457062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        binding.getHeaderAt(i),
12467062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
12477062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                if (pair.getFirst() != null) {
12487062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    list.addHeaderView(pair.getFirst());
12497062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                }
12507062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12517062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                skipCallbackParser |= pair.getSecond();
12527062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            }
12537062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12547062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            count = binding.getFooterCount();
12557062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            for (int i = 0 ; i < count ; i++) {
12567062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
12577062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        binding.getFooterAt(i),
12587062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
12597062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                if (pair.getFirst() != null) {
12607062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    list.addFooterView(pair.getFirst());
12617062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                }
12627062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12637062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                skipCallbackParser |= pair.getSecond();
12647062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            }
12657062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        }
12667062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12677062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        if (view instanceof ExpandableListView) {
12687062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ((ExpandableListView) view).setAdapter(
12697062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    new FakeExpandableAdapter(
12707062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
12717062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        } else {
12727062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ((AbsListView) view).setAdapter(
12737062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    new FakeAdapter(
12747062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
12757062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        }
12767062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    } else if (view instanceof AbsSpinner) {
12777062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        ((AbsSpinner) view).setAdapter(
12787062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                new FakeAdapter(
12797062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        listRef, binding, params.getProjectCallback()));
12807062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    }
12817062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                }
12827062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            }
12833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } else if (view instanceof ViewGroup) {
12843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            ViewGroup group = (ViewGroup)view;
12853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            final int count = group.getChildCount();
12863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            for (int c = 0 ; c < count ; c++) {
12873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                View child = group.getChildAt(c);
12883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                postInflateProcess(child, projectCallback);
12893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
12903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
12913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
12923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
12933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
12943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Sets up a {@link TabHost} object.
12953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param tabHost the TabHost to setup.
12963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param projectCallback The project callback object to access the project R class.
12973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @throws PostInflateException
12983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
12993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
13003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throws PostInflateException {
13013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // look for the TabWidget, and the FrameLayout. They have their own specific names
13023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        View v = tabHost.findViewById(android.R.id.tabs);
13033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (v == null) {
13053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(
13063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
13073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1309952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!(v instanceof TabWidget)) {
13103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(String.format(
13113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
13123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
13133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        v = tabHost.findViewById(android.R.id.tabcontent);
13163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (v == null) {
1318952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty)
1319952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            //noinspection SpellCheckingInspection
13203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(
13213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
13223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1324952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!(v instanceof FrameLayout)) {
1325952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            //noinspection SpellCheckingInspection
13263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(String.format(
13273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
13283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
13293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        FrameLayout content = (FrameLayout)v;
13323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1333952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        // now process the content of the frameLayout and dynamically create tabs for it.
13343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        final int count = content.getChildCount();
13353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // this must be called before addTab() so that the TabHost searches its TabWidget
13373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // and FrameLayout.
13383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        tabHost.setup();
13393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1340f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye        if (count == 0) {
1341f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            // Create a dummy child to get a single tab
1342f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label",
1343f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details))
1344f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    .setContent(new TabHost.TabContentFactory() {
1345d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                        @Override
1346f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                        public View createTabContent(String tag) {
13470fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                            return new LinearLayout(getContext());
1348f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                        }
1349f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    });
1350f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            tabHost.addTab(spec);
1351f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye        } else {
1352952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            // for each child of the frameLayout, add a new TabSpec
1353f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            for (int i = 0 ; i < count ; i++) {
1354f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                View child = content.getChildAt(i);
1355f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                String tabSpec = String.format("tab_spec%d", i+1);
1356f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                int id = child.getId();
1357952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                @SuppressWarnings("deprecation")
1358947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
1359f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                String name;
1360f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                if (resource != null) {
1361947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                    name = resource.getSecond();
1362f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                } else {
1363f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    name = String.format("Tab %d", i+1); // default name if id is unresolved.
1364f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                }
1365f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
13663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
13673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
13693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
137085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
137185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
137285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * bounds of all the views.
137385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
137485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param view the root View
137585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset for the view bounds.
137685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
137785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
137885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       content frame.
137985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
138085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
138185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
138285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
138385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isContentFrame) {
138485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
1385799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
138685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view instanceof ViewGroup) {
138785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            ViewGroup group = ((ViewGroup) view);
138885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
138985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    setExtendedInfo, isContentFrame));
139085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
139185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return result;
139285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1393799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
139485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
139585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
13968d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
139785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * the children of the {@code mContentRoot}.
139885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
139985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param viewGroup the root View
140085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset from the top for the content view frame.
140185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
140285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
140385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       content frame. {@code false} if the {@code ViewInfo} to be created is
140485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       part of the system decor.
140585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
140685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
140785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean setExtendedInfo, boolean isContentFrame) {
140885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (viewGroup == null) {
140985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return null;
1410799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        }
1411799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
141285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (!isContentFrame) {
141385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            offset += viewGroup.getTop();
141485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
1415799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
141685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        int childCount = viewGroup.getChildCount();
141785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (viewGroup == mContentRoot) {
141885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
141985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
142085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            for (int i = 0; i < childCount; i++) {
142185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
14226208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                        setExtendedInfo);
142385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                childrenWithoutOffset.add(childViewInfo[0]);
142485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                childrenWithOffset.add(childViewInfo[1]);
1425799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            }
142685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            mViewInfoList = childrenWithOffset;
142785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return childrenWithoutOffset;
142885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
142985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
143085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            for (int i = 0; i < childCount; i++) {
143185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
143285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        isContentFrame));
143385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            }
143485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return children;
1435799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        }
143685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1437799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
143885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
143985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
144085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
144185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * one with the {@code offset} and other without the {@code offset}. The offset is needed to
144285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
144385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
144485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * offset is not needed.
144585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
144685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
144785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *         index 1 is with the offset.
144885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
144985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
145085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo[] result = new ViewInfo[2];
145185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view == null) {
145285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return result;
145385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
145485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
145585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
145685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
145785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view instanceof ViewGroup) {
145885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
145985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result[0].setChildren(children);
146085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result[1].setChildren(children);
146185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
146285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return result;
1463799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    }
14643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
14653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
146685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
146785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
146885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * set.
146985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
14703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
147185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
147285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isContentFrame) {
14733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (view == null) {
14743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            return null;
14753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
14763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
147785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo result;
147885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (isContentFrame) {
147970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // The view is part of the layout added by the user. Hence,
148070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // the ViewCookie may be obtained only through the Context.
148185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result = new ViewInfo(view.getClass().getName(),
148270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    getContext().getViewKey(view),
148385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getLeft(), view.getTop() + offset, view.getRight(),
148485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getBottom() + offset, view, view.getLayoutParams());
148585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
148670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // We are part of the system decor.
148770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            SystemViewInfo r = new SystemViewInfo(view.getClass().getName(),
148841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta                    getViewKey(view),
148985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getLeft(), view.getTop(), view.getRight(),
149085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getBottom(), view, view.getLayoutParams());
149170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            result = r;
149270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // We currently mark three kinds of views:
149370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 1. Menus in the Action Bar
149470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 2. Menus in the Overflow popup.
149570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 3. The overflow popup button.
149670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            if (view instanceof ListMenuItemView) {
149770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // Mark 2.
149870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // All menus in the popup are of type ListMenuItemView.
149970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU);
150070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            } else {
150170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // Mark 3.
150270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                ViewGroup.LayoutParams lp = view.getLayoutParams();
150370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                if (lp instanceof ActionMenuView.LayoutParams &&
150470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        ((ActionMenuView.LayoutParams) lp).isOverflowButton) {
150570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    r.setViewType(ViewType.ACTION_BAR_OVERFLOW);
150670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                } else {
150770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // Mark 1.
150870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // A view is a menu in the Action Bar is it is not the overflow button and of
150970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // its parent is of type ActionMenuView. We can also check if the view is
151070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // instanceof ActionMenuItemView but that will fail for menus using
151170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // actionProviderClass.
151270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    ViewParent parent = view.getParent();
151370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    while (parent != mViewRoot && parent instanceof ViewGroup) {
151470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        if (parent instanceof ActionMenuView) {
151570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                            r.setViewType(ViewType.ACTION_BAR_MENU);
151670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                            break;
151770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        }
151870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        parent = parent.getParent();
151970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    }
152070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                }
152170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            }
152285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
15233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
15246208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet        if (setExtendedInfo) {
15256208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            MarginLayoutParams marginParams = null;
15266208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            LayoutParams params = view.getLayoutParams();
15276208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            if (params instanceof MarginLayoutParams) {
15286208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                marginParams = (MarginLayoutParams) params;
15296208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            }
15306208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            result.setExtendedInfo(view.getBaseline(),
15316208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.leftMargin : 0,
15326208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.topMargin : 0,
15336208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.rightMargin : 0,
15346208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.bottomMargin : 0);
15356208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet        }
15366208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet
15373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        return result;
15383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
15393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
154070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta    /* (non-Javadoc)
154141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     * The cookie for menu items are stored in menu item and not in the map from View stored in
154241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     * BridgeContext.
154341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     */
154441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta    private Object getViewKey(View view) {
154541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        BridgeContext context = getContext();
154641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (!(view instanceof MenuView.ItemView)) {
154741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            return context.getViewKey(view);
154841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
154941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        MenuItemImpl menuItem;
155041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (view instanceof ActionMenuItemView) {
155141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((ActionMenuItemView) view).getItemData();
155241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else if (view instanceof ListMenuItemView) {
155341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((ListMenuItemView) view).getItemData();
155441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else if (view instanceof IconMenuItemView) {
155541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((IconMenuItemView) view).getItemData();
155641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else {
155741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = null;
155841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
155941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (menuItem instanceof BridgeMenuItemImpl) {
156041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            return ((BridgeMenuItemImpl) menuItem).getViewCookie();
156141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
156241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta
156341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        return null;
156441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta    }
156541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta
156685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private void invalidateRenderingSize() {
156785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
156885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
156985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
1570799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    /**
157185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the status bar with wifi and battery icons.
1572799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     */
157385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
157485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isRtlSupported) throws XmlPullParserException {
157585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        StatusBar statusBar = new StatusBar(context, density,
157685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                direction, isRtlSupported);
157785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        statusBar.setLayoutParams(
157885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                new LinearLayout.LayoutParams(
157985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        LayoutParams.MATCH_PARENT, mStatusBarSize));
158085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return statusBar;
158185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1582e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
158385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
158485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the navigation bar with back, home and recent buttons.
158585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
158685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isRtl true if the current locale is right-to-left
158785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isRtlSupported true is the project manifest declares that the application
158885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *        is RTL aware.
158985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
159085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private NavigationBar createNavigationBar(BridgeContext context, Density density,
159185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isRtl, boolean isRtlSupported) throws XmlPullParserException {
159285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        NavigationBar navigationBar = new NavigationBar(context,
159385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                density, mNavigationBarOrientation, isRtl,
159485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                isRtlSupported);
159585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
159685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
159785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    LayoutParams.MATCH_PARENT));
159885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
159985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
160085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mNavigationBarSize));
1601e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet        }
160285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return navigationBar;
1603e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    }
1604e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
160585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private TitleBar createTitleBar(BridgeContext context, Density density, String title)
160685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            throws XmlPullParserException {
160785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        TitleBar titleBar = new TitleBar(context, density, title);
160885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        titleBar.setLayoutParams(
160985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
161085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return titleBar;
161185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1612e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
161385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
161485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the action bar. Also queries the project callback for missing information.
161585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
1616952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params) {
161785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ActionBarLayout actionBar = new ActionBarLayout(context, params);
161885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        actionBar.setLayoutParams(new LinearLayout.LayoutParams(
161985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
162085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return actionBar;
16211392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    }
16221392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
16233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    public BufferedImage getImage() {
16243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        return mImage;
16253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
16263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1627a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    public boolean isAlphaChannelImage() {
1628a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        return mIsAlphaChannelImage;
1629a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1630a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1631e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    public List<ViewInfo> getViewInfos() {
1632e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet        return mViewInfoList;
16333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
16342d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet
163585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    public List<ViewInfo> getSystemViewInfos() {
163685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return mSystemViewInfoList;
163785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
163885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
1639ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Map<String, String> getDefaultProperties(Object viewObject) {
16400fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        return getContext().getDefaultPropMap(viewObject);
16412d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet    }
1642b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
1643ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public void setScene(RenderSession session) {
1644ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        mScene = session;
1645b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
1646b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
1647ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public RenderSession getSession() {
1648b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        return mScene;
1649b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
16503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet}
1651