RenderSessionImpl.java revision 442aee6bc1abfb143dcfa1ba60d696e576d066c4
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
197062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding;
2064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig;
21ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener;
22ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser;
23b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport com.android.ide.common.rendering.api.LayoutlibCallback;
240d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources;
25ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession;
267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference;
27ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue;
28ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result;
29ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status;
30d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams;
31b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode;
3245d9520182663e47a1878ce51be756219799b2c9Deepanshu Guptaimport com.android.ide.common.rendering.api.StyleResourceValue;
33d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo;
3470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport com.android.ide.common.rendering.api.ViewType;
353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.internal.util.XmlUtils;
3641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView;
3741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl;
3841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView;
3941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView;
4041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl;
4141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuView;
42ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
44ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
46a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaevimport com.android.layoutlib.bridge.android.RenderParamsFlags;
47432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Guptaimport com.android.layoutlib.bridge.android.support.RecyclerViewUtil;
48841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Guptaimport com.android.layoutlib.bridge.bars.AppCompatActionBar;
49b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport com.android.layoutlib.bridge.bars.BridgeActionBar;
5082ca7fe915ed30a7e30eb3de3ce816a9ad0867d6Deepanshu Guptaimport com.android.layoutlib.bridge.bars.Config;
51b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport com.android.layoutlib.bridge.bars.FrameworkActionBar;
5264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.layoutlib.bridge.bars.NavigationBar;
5364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.layoutlib.bridge.bars.StatusBar;
54799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TitleBar;
557062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter;
567062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
5785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Guptaimport com.android.resources.Density;
581b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohetimport com.android.resources.ResourceType;
5964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.resources.ScreenOrientation;
60947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohetimport com.android.util.Pair;
613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
62799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException;
63799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
64994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.animation.AnimationThread;
6533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.Animator;
66ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport android.animation.AnimatorInflater;
6733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.LayoutTransition;
6862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener;
69442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.NonNull;
70442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.Nullable;
713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.app.Fragment_Delegate;
723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap;
733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap_Delegate;
743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Canvas;
753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.drawable.Drawable;
768a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Guptaimport android.preference.Preference_Delegate;
773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.DisplayMetrics;
783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.TypedValue;
79994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.AttachInfo_Accessor;
80994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.BridgeInflater;
8176f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.IWindowManager;
8264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport android.view.IWindowManagerImpl;
8376f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.Surface;
843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View;
853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View.MeasureSpec;
86d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.view.ViewGroup;
87ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport android.view.ViewGroup.LayoutParams;
886208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams;
8970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.view.ViewParent;
9076f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate;
917062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsListView;
927062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsSpinner;
9370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.widget.ActionMenuView;
947062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AdapterView;
957062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ExpandableListView;
963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.FrameLayout;
97f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.LinearLayout;
987062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ListView;
9962c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohetimport android.widget.QuickContactBadge;
1003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.TabHost;
101f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.TabHost.TabSpec;
102d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.widget.TabWidget;
1033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1044c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohetimport java.awt.AlphaComposite;
1053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Color;
1063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Graphics2D;
1073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.image.BufferedImage;
1083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.ArrayList;
1093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.List;
1103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.Map;
1113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
112b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
113b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
114b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
115b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
116b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
117b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
118b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta
1193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/**
120ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * Class implementing the render session.
121952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * <p/>
122ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming
123ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
1243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * be done on the layout.
1253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */
1260fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> {
1273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
1293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
1303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    // scene state
132ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private RenderSession mScene;
1333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BridgeXmlBlockParser mBlockParser;
1343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BridgeInflater mInflater;
1356a5b91fceb1913cab6416bef99d7b28530d16ecfXavier Ducrohet    private ResourceValue mWindowBackground;
136799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private ViewGroup mViewRoot;
137799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private FrameLayout mContentRoot;
1381392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private Canvas mCanvas;
1391392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private int mMeasuredScreenWidth = -1;
1401392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private int mMeasuredScreenHeight = -1;
141799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private boolean mIsAlphaChannelImage;
142799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private boolean mWindowIsFloating;
14345d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta    private Boolean mIsThemeAppCompat;
144a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
145a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private int mStatusBarSize;
14664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private int mNavigationBarSize;
14764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
148799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private int mTitleBarSize;
149799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private int mActionBarSize;
150a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    // information being returned through the API
1533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BufferedImage mImage;
154e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    private List<ViewInfo> mViewInfoList;
15585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private List<ViewInfo> mSystemViewInfoList;
1563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final class PostInflateException extends Exception {
1583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        private static final long serialVersionUID = 1L;
1593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        public PostInflateException(String message) {
1613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            super(message);
1623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
1633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
1643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
1663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Creates a layout scene with all the information coming from the layout bridge API.
1673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
1688d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
1698d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * which act as a
170ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * call to {@link RenderSessionImpl#acquire(long)}
1713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     *
1728d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * @see Bridge#createSession(SessionParams)
1733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
174b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohet    public RenderSessionImpl(SessionParams params) {
1750fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        super(new SessionParams(params));
176ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    }
177ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
178ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    /**
179ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
180ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * inflater, and parser.
181ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
182ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
183ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
184ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @return whether the scene was prepared
185ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
186ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @see #acquire(long)
187ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @see #release()
188ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     */
1890fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet    @Override
190ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result init(long timeout) {
1910fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        Result result = super.init(timeout);
192952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
193ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            return result;
194ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
1953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1960fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        SessionParams params = getParams();
1970fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
1983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
199835ad76e300033f1d9cccd214bd7d61d78d0240aDeepanshu Gupta
2000fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        RenderResources resources = getParams().getResources();
2010fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        DisplayMetrics metrics = getContext().getMetrics();
2023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
203a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // use default of true in case it's not found to use alpha by default
20445d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        mIsAlphaChannelImage  = getBooleanThemeValue(resources, "windowIsFloating", true, true);
20545d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        // FIXME: Find out why both variables are taking the same value.
20645d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating", true, true);
207ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
208a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        findBackground(resources);
209a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        findStatusBar(resources, metrics);
210799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        findActionBar(resources, metrics);
21164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        findNavigationBar(resources, metrics);
2123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
21376f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        // FIXME: find those out, and possibly add them to the render params
21476f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        boolean hasNavigationBar = true;
215952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        //noinspection ConstantConditions
21676f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
21776f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet                metrics, Surface.ROTATION_0,
2181e3c4a072f4476cedb958d75e2a6edf3bde8378fJohn Spurlock                hasNavigationBar);
21976f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
22076f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet
2213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // build the inflater and parser.
222b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta        mInflater = new BridgeInflater(context, params.getLayoutlibCallback());
2230fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        context.setBridgeInflater(mInflater);
224ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
225a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        mBlockParser = new BridgeXmlBlockParser(
226a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet                params.getLayoutDescription(), context, false /* platformResourceFlag */);
227ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
2283054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet        return SUCCESS.createResult();
2293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
2303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
2313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
2323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Inflates the layout.
2333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
234ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
235ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
236ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
237ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #init(long)} was not called.
2383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
239ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result inflate() {
240ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
241ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
2423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        try {
2433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
2440fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            SessionParams params = getParams();
24564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
2460fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            BridgeContext context = getContext();
247510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta            boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
24885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
24964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
250cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet            // the view group that receives the window background.
251952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            ViewGroup backgroundView;
252cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
2530fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            if (mWindowIsFloating || params.isForceNoDecor()) {
254cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
25585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                mViewRoot.setLayoutDirection(layoutDirection);
256799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            } else {
257bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                int simulatedPlatformVersion = params.getSimulatedPlatformVersion();
25864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
25964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    /*
26064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                     * This is a special case where the navigation bar is on the right.
26164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+---+
26264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | Status bar (always)                             |   |
26364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+   |
26464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | (Layout with background drawable)               |   |
26564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
26664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | | Title/Action bar (optional)                 | |   |
26764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
26864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | | Content, vertical extending                 | |   |
26964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | |                                             | |   |
27064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
27164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+---+
27264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
27364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       So we create a horizontal layout, with the nav bar on the right,
27464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       and the left part is the normal layout below without the nav bar at
27564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       the bottom
27664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                     */
27764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    LinearLayout topLayout = new LinearLayout(context);
27885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    topLayout.setLayoutDirection(layoutDirection);
27964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mViewRoot = topLayout;
28064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    topLayout.setOrientation(LinearLayout.HORIZONTAL);
28164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
282bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                    if (Config.showOnScreenNavBar(simulatedPlatformVersion)) {
283f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        try {
284f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                            NavigationBar navigationBar = createNavigationBar(context,
285bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                    hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
286bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                    simulatedPlatformVersion);
287f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                            topLayout.addView(navigationBar);
288f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        } catch (XmlPullParserException ignored) {
289f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        }
29064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    }
29164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                }
29264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
293799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                /*
294799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 * we're creating the following layout
295799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 *
296799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
29764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                   | Status bar (always)                             |
298799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
299cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | (Layout with background drawable)               |
300cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
301cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | | Title/Action bar (optional)                 | |
302cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
303cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | | Content, vertical extending                 | |
304cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | |                                             | |
305cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
306799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
30764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                   | Navigation bar for soft buttons, maybe see above|
308799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
309799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
310799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 */
311799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
3120fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                LinearLayout topLayout = new LinearLayout(context);
313799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                topLayout.setOrientation(LinearLayout.VERTICAL);
31485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                topLayout.setLayoutDirection(layoutDirection);
31564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // if we don't already have a view root this is it
31664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (mViewRoot == null) {
31764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mViewRoot = topLayout;
31864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                } else {
31985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    int topLayoutWidth =
32085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
32164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
32285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            topLayoutWidth, LayoutParams.MATCH_PARENT);
32364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    topLayout.setLayoutParams(layoutParams);
32464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
32564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // this is the case of soft buttons + vertical bar.
32664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // this top layout is the first layout in the horizontal layout. see above)
327510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    if (isRtl && params.isRtlSupported()) {
328510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // If RTL is enabled, layoutlib will mirror the layouts. So, add the
329510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // topLayout to the right of Navigation Bar and layoutlib will draw it
330510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // to the left.
331510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        mViewRoot.addView(topLayout);
332510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    } else {
333510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // Add the top layout to the left of the Navigation Bar.
334510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        mViewRoot.addView(topLayout, 0);
335510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    }
33664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                }
337799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
338799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (mStatusBarSize > 0) {
339799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // system bar
340799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
34185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
342f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                                layoutDirection, params.isRtlSupported(),
343bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                simulatedPlatformVersion);
34485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        topLayout.addView(statusBar);
345952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
346799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
347799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
348799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
349799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
350cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                LinearLayout backgroundLayout = new LinearLayout(context);
351cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundView = backgroundLayout;
352cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundLayout.setOrientation(LinearLayout.VERTICAL);
353cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
354fa7ed38ae9c180ff12a7312e6ec740b5ba313a97Deepanshu Gupta                        LayoutParams.MATCH_PARENT, 0);
355cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                layoutParams.weight = 1;
356cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundLayout.setLayoutParams(layoutParams);
357cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                topLayout.addView(backgroundLayout);
358cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
359cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
360799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // if the theme says no title/action bar, then the size will be 0
361799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (mActionBarSize > 0) {
362841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                    BridgeActionBar actionBar = createActionBar(context, params, backgroundLayout);
363952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    actionBar.createMenuPopup();
364952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    mContentRoot = actionBar.getContentRoot();
365799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                } else if (mTitleBarSize > 0) {
366799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
36785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        TitleBar titleBar = createTitleBar(context,
368bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                params.getAppLabel(),
369bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                simulatedPlatformVersion);
370cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                        backgroundLayout.addView(titleBar);
371952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
372799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
373799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
374799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
375799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
376799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // content frame
37785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                if (mContentRoot == null) {
37885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mContentRoot = new FrameLayout(context);
37985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    layoutParams = new LinearLayout.LayoutParams(
38085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            LayoutParams.MATCH_PARENT, 0);
38185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    layoutParams.weight = 1;
38285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mContentRoot.setLayoutParams(layoutParams);
38385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    backgroundLayout.addView(mContentRoot);
38485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                }
385799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
386bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                if (Config.showOnScreenNavBar(simulatedPlatformVersion) &&
387f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
38864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        mNavigationBarSize > 0) {
389799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // system bar
390799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
39185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        NavigationBar navigationBar = createNavigationBar(context,
392bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
393bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                simulatedPlatformVersion);
39464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        topLayout.addView(navigationBar);
395952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
396799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
397799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
398799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
399799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            }
400799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
4013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // Sets the project callback (custom view loader) to the fragment delegate so that
4033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // it can instantiate the custom Fragment.
404b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta            Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback());
4053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
406a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev            String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG);
4078a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            boolean isPreference = "PreferenceScreen".equals(rootTag);
4088a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            View view;
4098a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            if (isPreference) {
4108a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                view = Preference_Delegate.inflatePreference(getContext(), mBlockParser,
4118a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                  mContentRoot);
4128a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            } else {
4138a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                view = mInflater.inflate(mBlockParser, mContentRoot);
4148a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            }
4153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4167062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // done with the parser, pop it.
4177062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            context.popParser();
4187062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
419b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta            Fragment_Delegate.setLayoutlibCallback(null);
4203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // set the AttachInfo on the root view.
422994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet            AttachInfo_Accessor.setAttachInfo(mViewRoot);
4233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
424a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet            // post-inflate process. For now this supports TabHost/TabWidget
425b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta            postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null);
426a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet
4273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the background drawable
428952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            if (mWindowBackground != null) {
4290fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
43064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                backgroundView.setBackground(d);
4313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
433ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
4343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (PostInflateException e) {
435ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_INFLATION.createResult(e.getMessage(), e);
4363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (Throwable e) {
4373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the real cause of the exception.
4383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Throwable t = e;
4393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            while (t.getCause() != null) {
4403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                t = t.getCause();
4413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
443ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_INFLATION.createResult(t.getMessage(), t);
4443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
4453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
4463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
4483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Renders the scene.
4493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
450ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
451ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
4524c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     * @param freshRender whether the render is a new one and should erase the existing bitmap (in
4534c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *      the case where bitmaps are reused). This is typically needed when not playing
4544c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *      animations.)
4554c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *
456ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
457ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
4581392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet     *
4598d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * @see SessionParams#getRenderingMode()
460799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#render(long)
4613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
4624c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet    public Result render(boolean freshRender) {
463ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
464ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
4650fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        SessionParams params = getParams();
4660fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
4673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        try {
4683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (mViewRoot == null) {
469ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                return ERROR_NOT_INFLATED.createResult();
4703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4720fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            RenderingMode renderingMode = params.getRenderingMode();
47364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
474e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet
4751392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            // only do the screen measure when needed.
4761392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            boolean newRenderSize = false;
4771392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            if (mMeasuredScreenWidth == -1) {
4781392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                newRenderSize = true;
47964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
48064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
4811392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
4821392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                if (renderingMode != RenderingMode.NORMAL) {
4838ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
4848ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
4858ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            : MeasureSpec.EXACTLY;
4868ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    int heightMeasureSpecMode = renderingMode.isVertExpand() ?
4878ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
4888ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            : MeasureSpec.EXACTLY;
4898ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4908ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // We used to compare the measured size of the content to the screen size but
4918ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // this does not work anymore due to the 2 following issues:
4928ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // - If the content is in a decor (system bar, title/action bar), the root view
4938ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   will not resize even with the UNSPECIFIED because of the embedded layout.
4948ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // - If there is no decor, but a dialog frame, then the dialog padding prevents
4958ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   comparing the size of the content to the screen frame (as it would not
4968ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   take into account the dialog padding).
4978ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4988ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // The solution is to first get the content size in a normal rendering, inside
4998ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // the decor or the dialog padding.
5008ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // Then measure only the content with UNSPECIFIED to see the size difference
5018ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // and apply this to the screen size.
5028ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
5038ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // first measure the full layout, with EXACTLY to get the size of the
5048ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // content as it is inside the decor/dialog
505952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    @SuppressWarnings("deprecation")
5068ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    Pair<Integer, Integer> exactMeasure = measureView(
5078ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mViewRoot, mContentRoot.getChildAt(0),
5088ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth, MeasureSpec.EXACTLY,
5098ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight, MeasureSpec.EXACTLY);
5108ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
5118ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // now measure the content only using UNSPECIFIED (where applicable, based on
5128ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // the rendering mode). This will give us the size the content needs.
513952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    @SuppressWarnings("deprecation")
5148ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    Pair<Integer, Integer> result = measureView(
5158ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mContentRoot, mContentRoot.getChildAt(0),
5168ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth, widthMeasureSpecMode,
5178ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight, heightMeasureSpecMode);
5188ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
5198ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // now look at the difference and add what is needed.
5201392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    if (renderingMode.isHorizExpand()) {
5218ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int measuredWidth = exactMeasure.getFirst();
5228ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int neededWidth = result.getFirst();
5238ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        if (neededWidth > measuredWidth) {
5248ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth += neededWidth - measuredWidth;
5251392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                        }
526e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet                    }
5273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5281392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    if (renderingMode.isVertExpand()) {
5298ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int measuredHeight = exactMeasure.getSecond();
5308ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int neededHeight = result.getSecond();
5318ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        if (neededHeight > measuredHeight) {
5328ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight += neededHeight - measuredHeight;
5331392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                        }
534e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet                    }
5353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
5363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
5373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5388ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            // measure again with the size we need
5393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // This must always be done before the call to layout
5408ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            measureView(mViewRoot, null /*measuredView*/,
5418ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
5428ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
5433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // now do the layout.
545a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
5463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
547f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet            if (params.isLayoutOnly()) {
548f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // delete the canvas and image to reset them on the next full rendering
549f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mImage = null;
550f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mCanvas = null;
551f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet            } else {
552994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet                AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
553f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
554f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // draw the views
555f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // create the BufferedImage into which the layout will be rendered.
556f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                boolean newImage = false;
557e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez
558e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // When disableBitmapCaching is true, we do not reuse mImage and
559e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // we create a new one in every render.
560e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // This is useful when mImage is just a wrapper of Graphics2D so
561e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // it doesn't get cached.
562e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag(
563a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev                    RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING));
564e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                if (newRenderSize || mCanvas == null || disableBitmapCaching) {
565f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    if (params.getImageFactory() != null) {
566f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        mImage = params.getImageFactory().getImage(
567f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenWidth,
568f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenHeight);
569f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    } else {
570f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        mImage = new BufferedImage(
571f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenWidth,
572f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenHeight,
573f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                BufferedImage.TYPE_INT_ARGB);
574f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        newImage = true;
575f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    }
576f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
577f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    if (params.isBgColorOverridden()) {
578f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        // since we override the content, it's the same as if it was a new image.
579f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        newImage = true;
580f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        Graphics2D gc = mImage.createGraphics();
581f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.setColor(new Color(params.getOverrideBgColor(), true));
582f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.setComposite(AlphaComposite.Src);
583f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
584f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.dispose();
585f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    }
586f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
587f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    // create an Android bitmap around the BufferedImage
588f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
58964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                            true /*isMutable*/, hardwareConfig.getDensity());
590f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
591e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                    if (mCanvas == null) {
592e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                        // create a Canvas around the Android bitmap
593e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                        mCanvas = new Canvas(bitmap);
594e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                    } else {
595e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                        mCanvas.setBitmap(bitmap);
596e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                    }
59764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
5981392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                }
5993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
600952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                if (freshRender && !newImage) {
6011392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    Graphics2D gc = mImage.createGraphics();
6024c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet                    gc.setComposite(AlphaComposite.Src);
6033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
604f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.setColor(new Color(0x00000000, true));
605f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.fillRect(0, 0,
606f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                            mMeasuredScreenWidth, mMeasuredScreenHeight);
607a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
608f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    // done
609f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.dispose();
610f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                }
611a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
612f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mViewRoot.draw(mCanvas);
6134c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet            }
6144c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet
61541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
61641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta                    false);
6173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
6183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // success!
619ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
6203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (Throwable e) {
6213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the real cause of the exception.
6223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Throwable t = e;
6233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            while (t.getCause() != null) {
6243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                t = t.getCause();
6253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
6263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
627ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_UNKNOWN.createResult(t.getMessage(), t);
6283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
6293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
6303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
6313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
6328ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
6338ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
6348ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     *
6358ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
6368ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
6378ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     *
6388ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param viewToMeasure the view on which to execute measure().
6398ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param measuredView if non null, the view to query for its measured width/height.
6408ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param width the width to use in the MeasureSpec.
6418ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param widthMode the MeasureSpec mode to use for the width.
6428ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param height the height to use in the MeasureSpec.
6438ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param heightMode the MeasureSpec mode to use for the height.
6448ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @return the measured width/height if measuredView is non-null, null otherwise.
6458ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     */
646952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
6478ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
6488ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            int width, int widthMode, int height, int heightMode) {
6498ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
6508ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
6518ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        viewToMeasure.measure(w_spec, h_spec);
6528ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6538ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        if (measuredView != null) {
6548ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
6558ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        }
6568ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6578ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        return null;
6588ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    }
6598ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6608ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    /**
661ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * Animate an object
662ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * <p>
663ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
664ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
665ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
666ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
66733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
668799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
669ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     */
670ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result animate(Object targetObject, String animationName,
671ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            boolean isFrameworkAnimation, IAnimationListener listener) {
672ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
673ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
6740fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
6750fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
676ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        // find the animation file.
677952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        ResourceValue animationResource;
678ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        int animationId = 0;
679ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        if (isFrameworkAnimation) {
6800fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            animationResource = context.getRenderResources().getFrameworkResource(
6811b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
682ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            if (animationResource != null) {
683947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
684ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
685ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        } else {
6860fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            animationResource = context.getRenderResources().getProjectResource(
6871b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
688ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            if (animationResource != null) {
689b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                animationId = context.getLayoutlibCallback().getResourceId(
6901b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                        ResourceType.ANIMATOR, animationName);
691ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
692ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
693ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
694ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        if (animationResource != null) {
695ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            try {
6960fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                Animator anim = AnimatorInflater.loadAnimator(context, animationId);
697ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                if (anim != null) {
698ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                    anim.setTarget(targetObject);
699ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
70033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    new PlayAnimationThread(anim, this, animationName, listener).start();
701ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
702ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                    return SUCCESS.createResult();
703ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                }
704ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            } catch (Exception e) {
705b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                // get the real cause of the exception.
706b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                Throwable t = e;
707b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                while (t.getCause() != null) {
708b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                    t = t.getCause();
709b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                }
710b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
711ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                return ERROR_UNKNOWN.createResult(t.getMessage(), t);
712ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
713ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
714ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
715ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        return ERROR_ANIM_NOT_FOUND.createResult();
716b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
717b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
71833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
71933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Insert a new child into an existing parent.
72033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
72133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
72233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
72333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
72433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
72533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
726799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
72733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
728ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
72933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            final int index, IAnimationListener listener) {
730b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        checkLock();
731b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
7320fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
7330fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
734b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // create a block parser for the XML
735a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
736a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet                childXml, context, false /* platformResourceFlag */);
737b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
738b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // inflate the child without adding it to the root since we want to control where it'll
739b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // get added. We do pass the parentView however to ensure that the layoutParams will
740b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // be created correctly.
74133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
742a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        blockParser.ensurePopped();
743b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
74433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        invalidateRenderingSize();
74533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
74633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
74733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            new AnimationThread(this, "insertChild", listener) {
74833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
74933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
750ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                public Result preAnimation() {
75133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parentView.setLayoutTransition(new LayoutTransition());
75233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    return addView(parentView, child, index);
75333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
75433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
75533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
75633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                public void postAnimation() {
75733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parentView.setLayoutTransition(null);
75833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
75933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            }.start();
76033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
76133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
762ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult(child);
7631392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        }
7641392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
76533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        // add it to the parentView in the correct location
766ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        Result result = addView(parentView, child, index);
767952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
76833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
76933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
770b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
7714c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        result = render(false /*freshRender*/);
7721766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        if (result.isSuccess()) {
77333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            result = result.getCopyWithData(child);
7741766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        }
7751766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet
7761766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        return result;
777b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
778b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
77933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
78033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Adds a given view to a given parent at a given index.
78133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
78233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param parent the parent to receive the view
78333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param view the view to add to the parent
78433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param index the index where to do the add.
78533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
786ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
787ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
78833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
78933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
790ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private Result addView(ViewGroup parent, View view, int index) {
79133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        try {
79233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            parent.addView(view, index);
793ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
79433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        } catch (UnsupportedOperationException e) {
79533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
796ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
79733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
79833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
79933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
80033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
80133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Moves a view to a new parent at a given location
80233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
80333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
80433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
80533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
80633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
80733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
808799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
80933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
81062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet    public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
81124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
812b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        checkLock();
813b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
81433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        invalidateRenderingSize();
81533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
816ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        LayoutParams layoutParams = null;
81733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (layoutParamsMap != null) {
81833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // need to create a new LayoutParams object for the new parent.
81962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            layoutParams = newParentView.generateLayoutParams(
82033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
82133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
8221392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
82362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        // get the current parent of the view that needs to be moved.
82462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        final ViewGroup previousParent = (ViewGroup) childView.getParent();
82562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
82633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
82733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            final LayoutParams params = layoutParams;
828ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
82924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            // there is no support for animating views across layouts, so in case the new and old
83024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            // parent views are different we fake the animation through a no animation thread.
83124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            if (previousParent != newParentView) {
83224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                new Thread("not animated moveChild") {
83324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
83424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public void run() {
83524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        Result result = moveView(previousParent, newParentView, childView, index,
83624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                params);
837952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        if (!result.isSuccess()) {
83824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            listener.done(result);
83924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
84024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
84124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // ready to do the work, acquire the scene.
84224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        result = acquire(250);
843952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        if (!result.isSuccess()) {
84424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            listener.done(result);
84524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            return;
84624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
84724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
84824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        try {
8494c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet                            result = render(false /*freshRender*/);
85024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            if (result.isSuccess()) {
85124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                listener.onNewFrame(RenderSessionImpl.this.getSession());
85224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            }
85324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        } finally {
85424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            release();
85524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
85624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
85724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        listener.done(result);
85862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
85924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                }.start();
86024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            } else {
86124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                new AnimationThread(this, "moveChild", listener) {
86262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
86324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
86424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public Result preAnimation() {
86524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // set up the transition for the parent.
86624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        LayoutTransition transition = new LayoutTransition();
86724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        previousParent.setLayoutTransition(transition);
8685562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet
86924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // tweak the animation durations and start delays (to match the duration of
87024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // animation playing just before).
87124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // Note: Cannot user Animation.setDuration() directly. Have to set it
87224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // on the LayoutTransition.
87324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
87424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // CHANGE_DISAPPEARING plays after DISAPPEARING
87524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
876ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
87724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
87824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
87924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
88024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // CHANGE_APPEARING plays after CHANGE_APPEARING
88124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
88224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
88324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.APPEARING, 100);
88424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
88524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        return moveView(previousParent, newParentView, childView, index, params);
88624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    }
88724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
88824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
88924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public void postAnimation() {
89024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        previousParent.setLayoutTransition(null);
89124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        newParentView.setLayoutTransition(null);
89224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    }
89324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                }.start();
89424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            }
89533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
89633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
897ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult(layoutParams);
898b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        }
899b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
90062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
901952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
90233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
90333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
904b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
9054c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        result = render(false /*freshRender*/);
906ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        if (layoutParams != null && result.isSuccess()) {
90733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            result = result.getCopyWithData(layoutParams);
908ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        }
909ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
910ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        return result;
911b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
912b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
91333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
91433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Moves a View from its current parent to a new given parent at a new given location, with
91533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * an optional new {@link LayoutParams} instance
91633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
91762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet     * @param previousParent the previous parent, still owning the child at the time of the call.
91862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet     * @param newParent the new parent
91924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet     * @param movedView the view to move
92033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param index the new location in the new parent
92133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param params an option (can be null) {@link LayoutParams} instance.
92233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
923ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
924ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
92533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
92633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
92724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
92824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            final View movedView, final int index, final LayoutParams params) {
9291392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        try {
93062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            // check if there is a transition on the previousParent.
93124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            LayoutTransition previousTransition = previousParent.getLayoutTransition();
93224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            if (previousTransition != null) {
9335562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // in this case there is an animation. This means we have to wait for the child's
9345562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // parent reference to be null'ed out so that we can add it to the new parent.
9355562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // It is technically removed right before the DISAPPEARING animation is done (if
9365562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // the animation of this type is not null, otherwise it's after which is impossible
9375562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // to handle).
9385562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // Because there is no move animation, if the new parent is the same as the old
9395562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
9405562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // adding the child or the child will appear in its new location before the
9415562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // other children have made room for it.
94262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
94362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // add a listener to the transition to be notified of the actual removal.
94424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousTransition.addTransitionListener(new TransitionListener() {
94524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    private int mChangeDisappearingCount = 0;
94662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
947d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                    @Override
94862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    public void startTransition(LayoutTransition transition, ViewGroup container,
94962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            View view, int transitionType) {
95024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
95124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            mChangeDisappearingCount++;
95224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
95362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
95433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
955d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                    @Override
95662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    public void endTransition(LayoutTransition transition, ViewGroup container,
95762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            View view, int transitionType) {
95824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
95924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            mChangeDisappearingCount--;
96024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
96124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
96224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
96324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                mChangeDisappearingCount == 0) {
96462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            // add it to the parentView in the correct location
96562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            if (params != null) {
96624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                newParent.addView(movedView, index, params);
96762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            } else {
96824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                newParent.addView(movedView, index);
96962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            }
97062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                        }
97162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
97262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                });
97362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
97462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // remove the view from the current parent.
97524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousParent.removeView(movedView);
97662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
97762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // and return since adding the view to the new parent is done in the listener.
97862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                return SUCCESS.createResult();
97933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            } else {
98062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // standard code with no animation. pretty simple.
98124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousParent.removeView(movedView);
98233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
98362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // add it to the parentView in the correct location
98462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                if (params != null) {
98524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    newParent.addView(movedView, index, params);
98662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                } else {
98724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    newParent.addView(movedView, index);
98862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                }
98962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
99062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                return SUCCESS.createResult();
99162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            }
9921392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        } catch (UnsupportedOperationException e) {
9931392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
994ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
995b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        }
99633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
99733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
99833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
99933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Removes a child from its current parent.
100033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
100133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
100233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
100333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
100433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
100533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
1006799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#removeChild(Object, IAnimationListener)
100733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
1008ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result removeChild(final View childView, IAnimationListener listener) {
100933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        checkLock();
1010b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
10111392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        invalidateRenderingSize();
10121392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
101333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        final ViewGroup parent = (ViewGroup) childView.getParent();
101433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
101533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
101633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            new AnimationThread(this, "moveChild", listener) {
101733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
101833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
1019ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                public Result preAnimation() {
102033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parent.setLayoutTransition(new LayoutTransition());
102133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    return removeView(parent, childView);
102233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
102333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
102433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
102533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                public void postAnimation() {
102633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parent.setLayoutTransition(null);
102733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
102833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            }.start();
102933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
103033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
1031ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
103233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
103333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
1034ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        Result result = removeView(parent, childView);
1035952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
103633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
103733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
103833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
10394c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        return render(false /*freshRender*/);
1040ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    }
1041ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
1042ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    /**
104333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Removes a given view from its current parent.
104433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
104533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param view the view to remove from its parent
104633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
1047ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
1048ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
104933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
105033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
1051ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private Result removeView(ViewGroup parent, View view) {
105233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        try {
105333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            parent.removeView(view);
1054ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
105533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        } catch (UnsupportedOperationException e) {
105633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
1057ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
105833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
105933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
106033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
1061ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
1062a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private void findBackground(RenderResources resources) {
1063952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!getParams().isBgColorOverridden()) {
106441fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet            mWindowBackground = resources.findItemInTheme("windowBackground",
106541fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                    true /*isFrameworkAttr*/);
1066a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            if (mWindowBackground != null) {
1067a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                mWindowBackground = resources.resolveResValue(mWindowBackground);
1068a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1069a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1070a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
10713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
107264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private boolean hasSoftwareButtons() {
107364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        return getParams().getHardwareConfig().hasSoftwareButtons();
1074a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
10753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1076a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
107764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        boolean windowFullscreen = getBooleanThemeValue(resources,
10782464a94e51e32f38613b86d4b1a995e2cf2d33e3Deepanshu Gupta                "windowFullscreen", false, true);
1079a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1080952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!windowFullscreen && !mWindowIsFloating) {
108164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            // default value
108264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
1083a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
108464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            // get the real value
108564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
108664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    "status_bar_height");
1087a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
108864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (value != null) {
108964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
109064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        value.getValue(), true /*requireUnit*/);
109164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (typedValue != null) {
109264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // compute the pixel value based on the display metrics
109364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mStatusBarSize = (int)typedValue.getDimension(metrics);
1094a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                }
1095a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1096a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1097a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1098a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1099799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
1100799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        if (mWindowIsFloating) {
1101799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            return;
1102a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1103a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1104a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        boolean windowActionBar = getBooleanThemeValue(resources,
110545d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta                "windowActionBar", true, !isThemeAppCompat(resources));
1106a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1107a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // if there's a value and it's false (default is true)
1108a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        if (windowActionBar) {
11093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // default size of the window title bar
1111799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
11123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get value from the theme.
111441fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet            ResourceValue value = resources.findItemInTheme("actionBarSize",
111541fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                    true /*isFrameworkAttr*/);
11163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // resolve it
1118a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            value = resources.resolveResValue(value);
11193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (value != null) {
11213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                // get the numerical value, if available
1122d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
1123d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                        true /*requireUnit*/);
11243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                if (typedValue != null) {
11253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    // compute the pixel value based on the display metrics
1126799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    mActionBarSize = (int)typedValue.getDimension(metrics);
11273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
11283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
1129799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        } else {
1130799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            // action bar overrides title bar so only look for this one if action bar is hidden
1131531a6693ac4a950e4c3ab6135112fcabd1887addDeepanshu Gupta            boolean windowNoTitle = getBooleanThemeValue(resources, "windowNoTitle", false, true);
11323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1133952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            if (!windowNoTitle) {
1134a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1135799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // default size of the window title bar
1136799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
1137a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1138799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // get value from the theme.
113941fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                ResourceValue value = resources.findItemInTheme("windowTitleSize",
114041fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                        true /*isFrameworkAttr*/);
1141a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1142799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // resolve it
1143799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                value = resources.resolveResValue(value);
11443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1145799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (value != null) {
1146799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // get the numerical value, if available
1147d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                    TypedValue typedValue = ResourceHelper.getValue("windowTitleSize",
1148d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                            value.getValue(), true /*requireUnit*/);
1149799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    if (typedValue != null) {
1150799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                        // compute the pixel value based on the display metrics
1151799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                        mTitleBarSize = (int)typedValue.getDimension(metrics);
1152799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
1153a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                }
1154a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1155799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
1156a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1157a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1158a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
115964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
1160952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (hasSoftwareButtons() && !mWindowIsFloating) {
11613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // default value
116364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            mNavigationBarSize = 48; // ??
116464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
116564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = getParams().getHardwareConfig();
116664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
116764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            boolean barOnBottom = true;
116864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
116964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
117064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // compute the dp of the screen.
117164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                int shortSize = hardwareConfig.getScreenHeight();
117264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
117364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // compute in dp
1174952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /
1175952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        hardwareConfig.getDensity().getDpiValue();
117664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
1177952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                // 0-599dp: "phone" UI with bar on the side
1178952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                // 600+dp: "tablet" UI with bar on the bottom
1179952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                barOnBottom = shortSizeDp >= 600;
118064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            }
118164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
118264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (barOnBottom) {
118364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mNavigationBarOrientation = LinearLayout.HORIZONTAL;
118464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            } else {
118564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mNavigationBarOrientation = LinearLayout.VERTICAL;
118664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            }
11873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1188089143ffed72bb47fd8d870f29caffb646138781Xavier Ducrohet            // get the real value
11891b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
119064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
1191a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
11923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (value != null) {
119364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
1194d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
11953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                if (typedValue != null) {
11963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    // compute the pixel value based on the display metrics
119764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mNavigationBarSize = (int)typedValue.getDimension(metrics);
11983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
11993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
1200a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1201a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1202a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
120345d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta    private boolean isThemeAppCompat(RenderResources resources) {
120445d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        // Ideally, we should check if the corresponding activity extends
120545d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
120645d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        if (mIsThemeAppCompat == null) {
120745d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta            StyleResourceValue defaultTheme = resources.getDefaultTheme();
1208841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta          // We can't simply check for parent using resources.themeIsParentOf() since the
1209841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta          // inheritance structure isn't really what one would expect. The first common parent
1210841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta          // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
1211841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            boolean isThemeAppCompat = false;
1212841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            for (int i = 0; i < 50; i++) {
12133da4ded958f2e1d5a7ffbddd62b46cf179e61fe9Diego Perez                if (defaultTheme == null) {
12143da4ded958f2e1d5a7ffbddd62b46cf179e61fe9Diego Perez                    break;
12153da4ded958f2e1d5a7ffbddd62b46cf179e61fe9Diego Perez                }
1216841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                // for loop ensures that we don't run into cyclic theme inheritance.
1217841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                if (defaultTheme.getName().startsWith("Theme.AppCompat")) {
1218841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                    isThemeAppCompat = true;
1219841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                    break;
1220841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                }
1221841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                defaultTheme = resources.getParent(defaultTheme);
1222841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            }
1223841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            mIsThemeAppCompat = isThemeAppCompat;
122445d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        }
122545d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        return mIsThemeAppCompat;
122645d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta    }
122745d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta
122841fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet    /**
122945d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta     * Looks for an attribute in the current theme.
123041fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     *
123141fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param resources the render resources
123241fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param name the name of the attribute
123341fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param defaultValue the default value.
123445d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta     * @param isFrameworkAttr if the attribute is in android namespace
123541fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @return the value of the attribute or the default one if not found.
123641fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     */
1237a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private boolean getBooleanThemeValue(RenderResources resources,
123845d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta            String name, boolean defaultValue, boolean isFrameworkAttr) {
1239a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
124045d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr);
1241a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1242a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // because it may reference something else, we resolve it.
1243a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        value = resources.resolveResValue(value);
12443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1245a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // if there's no value, return the default.
1246a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        if (value == null || value.getValue() == null) {
1247a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            return defaultValue;
12483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
12493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1250a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
12513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
12523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
12533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
1254952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * Post process on a view hierarchy that was just inflated.
1255952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * <p/>
1256952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the
12573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
12583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * based on the content of the {@link FrameLayout}.
12593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param view the root view to process.
1260b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta     * @param layoutlibCallback callback to the project.
12618a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta     * @param skip the view and it's children are not processed.
12623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
1263952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
1264b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta    private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip)
12653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throws PostInflateException {
12668a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta        if (view == skip) {
12678a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            return;
12688a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta        }
12693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (view instanceof TabHost) {
1270b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta            setupTabHost((TabHost) view, layoutlibCallback);
127162c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet        } else if (view instanceof QuickContactBadge) {
127262c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet            QuickContactBadge badge = (QuickContactBadge) view;
127362c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet            badge.setImageToDefault();
12747062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet        } else if (view instanceof AdapterView<?>) {
12757062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // get the view ID.
12767062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            int id = view.getId();
12777062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12787062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            BridgeContext context = getContext();
12797062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12807062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // get a ResourceReference from the integer ID.
12817062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            ResourceReference listRef = context.resolveId(id);
12827062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12837062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            if (listRef != null) {
12847062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                SessionParams params = getParams();
12857062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                AdapterBinding binding = params.getAdapterBindings().get(listRef);
12867062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12877062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                // if there was no adapter binding, trying to get it from the call back.
12887062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                if (binding == null) {
1289b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                    binding = layoutlibCallback.getAdapterBinding(
1290b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                            listRef, context.getViewKey(view), view);
12917062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                }
12927062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12937062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                if (binding != null) {
12947062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12957062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    if (view instanceof AbsListView) {
12967062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) &&
12977062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                view instanceof ListView) {
12987062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ListView list = (ListView) view;
12997062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13007062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            boolean skipCallbackParser = false;
13017062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13027062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            int count = binding.getHeaderCount();
13038a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                            for (int i = 0; i < count; i++) {
13047062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
13057062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        binding.getHeaderAt(i),
1306b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                                        list, false, skipCallbackParser);
13077062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                if (pair.getFirst() != null) {
13087062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    list.addHeaderView(pair.getFirst());
13097062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                }
13107062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13117062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                skipCallbackParser |= pair.getSecond();
13127062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            }
13137062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13147062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            count = binding.getFooterCount();
13158a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                            for (int i = 0; i < count; i++) {
13167062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
13177062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        binding.getFooterAt(i),
1318b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                                        list, false, skipCallbackParser);
13197062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                if (pair.getFirst() != null) {
13207062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    list.addFooterView(pair.getFirst());
13217062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                }
13227062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13237062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                skipCallbackParser |= pair.getSecond();
13247062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            }
13257062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        }
13267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13277062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        if (view instanceof ExpandableListView) {
13287062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ((ExpandableListView) view).setAdapter(
1329b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                                    new FakeExpandableAdapter(listRef, binding, layoutlibCallback));
13307062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        } else {
13317062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ((AbsListView) view).setAdapter(
1332b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                                    new FakeAdapter(listRef, binding, layoutlibCallback));
13337062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        }
13347062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    } else if (view instanceof AbsSpinner) {
13357062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        ((AbsSpinner) view).setAdapter(
1336b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                                new FakeAdapter(listRef, binding, layoutlibCallback));
13377062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    }
13387062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                }
13397062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            }
1340432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta        } else if (isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) {
1341432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta            RecyclerViewUtil.setAdapter(view, getContext(), getParams());
13423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } else if (view instanceof ViewGroup) {
13438a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            ViewGroup group = (ViewGroup) view;
13443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            final int count = group.getChildCount();
13458a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            for (int c = 0; c < count; c++) {
13463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                View child = group.getChildAt(c);
1347b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                postInflateProcess(child, layoutlibCallback, skip);
13483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
13493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
13513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
1353432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta     * Check if the object is an instance of a class named {@code className}. This doesn't work
1354432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta     * for interfaces.
1355432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta     */
1356432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta    public static boolean isInstanceOf(Object object, String className) {
1357432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta        Class superClass = object.getClass();
1358432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta        while (superClass != null) {
1359432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta            String name = superClass.getName();
1360432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta            if (name.equals(className)) {
1361432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta                return true;
1362432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta            }
1363432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta            superClass = superClass.getSuperclass();
1364432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta        }
1365432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta        return false;
1366432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta    }
1367432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta
1368432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta    /**
13693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Sets up a {@link TabHost} object.
13703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param tabHost the TabHost to setup.
1371b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta     * @param layoutlibCallback The project callback object to access the project R class.
13723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @throws PostInflateException
13733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
1374b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta    private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback)
13753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throws PostInflateException {
13763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // look for the TabWidget, and the FrameLayout. They have their own specific names
13773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        View v = tabHost.findViewById(android.R.id.tabs);
13783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (v == null) {
13803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(
13813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
13823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1384952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!(v instanceof TabWidget)) {
13853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(String.format(
13863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
13873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
13883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        v = tabHost.findViewById(android.R.id.tabcontent);
13913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (v == null) {
1393952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty)
1394952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            //noinspection SpellCheckingInspection
13953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(
13963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
13973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1399952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!(v instanceof FrameLayout)) {
1400952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            //noinspection SpellCheckingInspection
14013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(String.format(
14023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
14033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
14043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
14053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
14063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        FrameLayout content = (FrameLayout)v;
14073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1408952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        // now process the content of the frameLayout and dynamically create tabs for it.
14093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        final int count = content.getChildCount();
14103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
14113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // this must be called before addTab() so that the TabHost searches its TabWidget
14123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // and FrameLayout.
14133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        tabHost.setup();
14143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1415f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye        if (count == 0) {
1416f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            // Create a dummy child to get a single tab
14176257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta            TabSpec spec = tabHost.newTabSpec("tag")
14186257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta                    .setIndicator("Tab Label", tabHost.getResources()
14196257175afa5c892cb0a7cd14d958418c1720cb84Deepanshu Gupta                            .getDrawable(android.R.drawable.ic_menu_info_details, null))
1420f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    .setContent(new TabHost.TabContentFactory() {
1421d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                        @Override
1422f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                        public View createTabContent(String tag) {
14230fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                            return new LinearLayout(getContext());
1424f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                        }
1425f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    });
1426f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            tabHost.addTab(spec);
1427f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye        } else {
1428952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            // for each child of the frameLayout, add a new TabSpec
1429f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            for (int i = 0 ; i < count ; i++) {
1430f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                View child = content.getChildAt(i);
1431f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                String tabSpec = String.format("tab_spec%d", i+1);
14328a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                @SuppressWarnings("ConstantConditions")  // child cannot be null.
1433f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                int id = child.getId();
1434952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                @SuppressWarnings("deprecation")
1435b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id);
1436f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                String name;
1437f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                if (resource != null) {
1438947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                    name = resource.getSecond();
1439f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                } else {
1440f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    name = String.format("Tab %d", i+1); // default name if id is unresolved.
1441f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                }
1442f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
14433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
14443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
14453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
14463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
144785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
144885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
144985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * bounds of all the views.
145085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
145185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param view the root View
145285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset for the view bounds.
145385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
145485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
145585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       content frame.
145685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
145785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
145885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
145985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
146085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isContentFrame) {
146185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
1462799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
146385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view instanceof ViewGroup) {
146485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            ViewGroup group = ((ViewGroup) view);
146585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
146685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    setExtendedInfo, isContentFrame));
146785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
146885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return result;
146985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1470799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
147185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
147285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
14738d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
147485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * the children of the {@code mContentRoot}.
147585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
147685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param viewGroup the root View
147785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset from the top for the content view frame.
147885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
147985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
148085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       content frame. {@code false} if the {@code ViewInfo} to be created is
148185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       part of the system decor.
148285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
148385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
148485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean setExtendedInfo, boolean isContentFrame) {
148585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (viewGroup == null) {
148685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return null;
1487799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        }
1488799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
148985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (!isContentFrame) {
149085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            offset += viewGroup.getTop();
149185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
1492799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
149385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        int childCount = viewGroup.getChildCount();
149485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (viewGroup == mContentRoot) {
149585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
149685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
149785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            for (int i = 0; i < childCount; i++) {
149885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
14996208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                        setExtendedInfo);
150085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                childrenWithoutOffset.add(childViewInfo[0]);
150185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                childrenWithOffset.add(childViewInfo[1]);
1502799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            }
150385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            mViewInfoList = childrenWithOffset;
150485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return childrenWithoutOffset;
150585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
150685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
150785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            for (int i = 0; i < childCount; i++) {
150885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
150985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        isContentFrame));
151085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            }
151185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return children;
1512799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        }
151385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1514799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
151585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
151685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
151785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
151885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * one with the {@code offset} and other without the {@code offset}. The offset is needed to
151985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
152085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
152185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * offset is not needed.
152285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
152385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
152485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *         index 1 is with the offset.
152585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
1526432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta    @NonNull
152785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
152885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo[] result = new ViewInfo[2];
152985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view == null) {
153085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return result;
153185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
153285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
153385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
153485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
153585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view instanceof ViewGroup) {
153685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
153785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result[0].setChildren(children);
153885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result[1].setChildren(children);
153985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
154085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return result;
1541799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    }
15423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
15433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
154485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
154585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
154685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * set.
154785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
15483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
154985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
155085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isContentFrame) {
15513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (view == null) {
15523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            return null;
15533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
15543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
155585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo result;
155685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (isContentFrame) {
155770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // The view is part of the layout added by the user. Hence,
155870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // the ViewCookie may be obtained only through the Context.
155985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result = new ViewInfo(view.getClass().getName(),
156070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    getContext().getViewKey(view),
156185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getLeft(), view.getTop() + offset, view.getRight(),
156285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getBottom() + offset, view, view.getLayoutParams());
156385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
156470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // We are part of the system decor.
156570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            SystemViewInfo r = new SystemViewInfo(view.getClass().getName(),
156641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta                    getViewKey(view),
156785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getLeft(), view.getTop(), view.getRight(),
156885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getBottom(), view, view.getLayoutParams());
156970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            result = r;
157070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // We currently mark three kinds of views:
157170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 1. Menus in the Action Bar
157270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 2. Menus in the Overflow popup.
157370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 3. The overflow popup button.
157470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            if (view instanceof ListMenuItemView) {
157570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // Mark 2.
157670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // All menus in the popup are of type ListMenuItemView.
157770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU);
157870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            } else {
157970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // Mark 3.
158070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                ViewGroup.LayoutParams lp = view.getLayoutParams();
158170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                if (lp instanceof ActionMenuView.LayoutParams &&
158270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        ((ActionMenuView.LayoutParams) lp).isOverflowButton) {
158370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    r.setViewType(ViewType.ACTION_BAR_OVERFLOW);
158470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                } else {
158570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // Mark 1.
158670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // A view is a menu in the Action Bar is it is not the overflow button and of
158770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // its parent is of type ActionMenuView. We can also check if the view is
158870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // instanceof ActionMenuItemView but that will fail for menus using
158970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // actionProviderClass.
159070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    ViewParent parent = view.getParent();
159170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    while (parent != mViewRoot && parent instanceof ViewGroup) {
159270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        if (parent instanceof ActionMenuView) {
159370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                            r.setViewType(ViewType.ACTION_BAR_MENU);
159470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                            break;
159570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        }
159670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        parent = parent.getParent();
159770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    }
159870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                }
159970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            }
160085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
16013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
16026208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet        if (setExtendedInfo) {
16036208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            MarginLayoutParams marginParams = null;
16046208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            LayoutParams params = view.getLayoutParams();
16056208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            if (params instanceof MarginLayoutParams) {
16066208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                marginParams = (MarginLayoutParams) params;
16076208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            }
16086208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            result.setExtendedInfo(view.getBaseline(),
16096208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.leftMargin : 0,
16106208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.topMargin : 0,
16116208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.rightMargin : 0,
16126208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.bottomMargin : 0);
16136208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet        }
16146208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet
16153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        return result;
16163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
16173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
161870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta    /* (non-Javadoc)
161941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     * The cookie for menu items are stored in menu item and not in the map from View stored in
162041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     * BridgeContext.
162141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     */
1622432578acb80cf2fa827ddb9595cf46edf0b340b0Deepanshu Gupta    @Nullable
162341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta    private Object getViewKey(View view) {
162441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        BridgeContext context = getContext();
162541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (!(view instanceof MenuView.ItemView)) {
162641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            return context.getViewKey(view);
162741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
162841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        MenuItemImpl menuItem;
162941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (view instanceof ActionMenuItemView) {
163041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((ActionMenuItemView) view).getItemData();
163141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else if (view instanceof ListMenuItemView) {
163241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((ListMenuItemView) view).getItemData();
163341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else if (view instanceof IconMenuItemView) {
163441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((IconMenuItemView) view).getItemData();
163541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else {
163641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = null;
163741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
163841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (menuItem instanceof BridgeMenuItemImpl) {
163941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            return ((BridgeMenuItemImpl) menuItem).getViewCookie();
164041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
164141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta
164241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        return null;
164341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta    }
164441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta
1645620f80a7ee9796c2c41ec0a42d10d2913fc50c90Diego Perez    public void invalidateRenderingSize() {
164685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
164785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
164885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
1649799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    /**
165085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the status bar with wifi and battery icons.
1651799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     */
165285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
1653f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta            boolean isRtlSupported, int platformVersion) throws XmlPullParserException {
165485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        StatusBar statusBar = new StatusBar(context, density,
1655f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                direction, isRtlSupported, platformVersion);
165685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        statusBar.setLayoutParams(
165785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                new LinearLayout.LayoutParams(
165885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        LayoutParams.MATCH_PARENT, mStatusBarSize));
165985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return statusBar;
166085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1661e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
166285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
166385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the navigation bar with back, home and recent buttons.
166485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
166585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isRtl true if the current locale is right-to-left
166685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isRtlSupported true is the project manifest declares that the application
166785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *        is RTL aware.
166885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
166985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private NavigationBar createNavigationBar(BridgeContext context, Density density,
1670bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta            boolean isRtl, boolean isRtlSupported, int simulatedPlatformVersion)
1671bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta            throws XmlPullParserException {
167285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        NavigationBar navigationBar = new NavigationBar(context,
167385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                density, mNavigationBarOrientation, isRtl,
1674bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                isRtlSupported, simulatedPlatformVersion);
167585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
167685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
167785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    LayoutParams.MATCH_PARENT));
167885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
167985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
168085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mNavigationBarSize));
1681e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet        }
168285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return navigationBar;
1683e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    }
1684e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
1685bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta    private TitleBar createTitleBar(BridgeContext context, String title,
1686bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta            int simulatedPlatformVersion)
168785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            throws XmlPullParserException {
1688bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta        TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
168985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        titleBar.setLayoutParams(
169085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
169185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return titleBar;
169285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1693e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
169485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
169585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the action bar. Also queries the project callback for missing information.
169685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
1697841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta    private BridgeActionBar createActionBar(BridgeContext context, SessionParams params,
1698cc1ce2c8d83464c7be38e3281bf8da3963505a9bDeepanshu Gupta            ViewGroup parentView) {
1699841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta        if (mIsThemeAppCompat == Boolean.TRUE) {
1700841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            return new AppCompatActionBar(context, params, parentView);
1701841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta        } else {
1702841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            return new FrameworkActionBar(context, params, parentView);
1703841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta        }
17041392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    }
17051392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
17063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    public BufferedImage getImage() {
17073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        return mImage;
17083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
17093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1710a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    public boolean isAlphaChannelImage() {
1711a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        return mIsAlphaChannelImage;
1712a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1713a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1714e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    public List<ViewInfo> getViewInfos() {
1715e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet        return mViewInfoList;
17163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
17172d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet
171885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    public List<ViewInfo> getSystemViewInfos() {
171985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return mSystemViewInfoList;
172085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
172185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
1722ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Map<String, String> getDefaultProperties(Object viewObject) {
17230fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        return getContext().getDefaultPropMap(viewObject);
17242d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet    }
1725b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
1726ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public void setScene(RenderSession session) {
1727ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        mScene = session;
1728b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
1729b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
1730ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public RenderSession getSession() {
1731b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        return mScene;
1732b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
17333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet}
1734