RenderAction.java revision 0a49635b171f3ba366b1a7ebf28791c4661829bd
1b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet/*
2b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
3b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
4b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
5b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * you may not use this file except in compliance with the License.
6b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * You may obtain a copy of the License at
7b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
8b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
9b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
10b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software
11b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
12b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * See the License for the specific language governing permissions and
14b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * limitations under the License.
15b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet */
16b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
17b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpackage com.android.layoutlib.bridge.impl;
18b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
19b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED;
20b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
21b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
22b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
23b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog;
24b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderParams;
25b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources;
26b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.ide.common.rendering.api.Result;
27b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
28b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
29b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
300a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohetimport com.android.resources.Density;
31b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.resources.ResourceType;
320a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohetimport com.android.resources.ScreenSize;
33b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
340a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohetimport android.content.res.Configuration;
35fb93ce9684120a36862b5b5e67b1865a652907e9Xavier Ducrohetimport android.os.HandlerThread_Delegate;
36b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport android.util.DisplayMetrics;
370a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohetimport android.view.ViewConfiguration;
38b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
39b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport java.util.concurrent.TimeUnit;
40b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport java.util.concurrent.locks.ReentrantLock;
41b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
42b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet/**
43fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * Base class for rendering action.
44fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet *
45fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * It provides life-cycle methods to init and stop the rendering.
46fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * The most important methods are:
47fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * {@link #init(long)} and {@link #acquire(long)} to start a rendering and {@link #release()}
48fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet * after the rendering.
49b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
50b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
51b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * @param <T> the {@link RenderParams} implementation
52b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
53b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet */
54fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohetpublic abstract class RenderAction<T extends RenderParams> extends FrameworkResourceIdProvider {
55b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
56b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
57b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The current context being rendered. This is set through {@link #acquire(long)} and
58b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * {@link #init(long)}, and unset in {@link #release()}.
59b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
60b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private static BridgeContext sCurrentContext = null;
61b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
62b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private final T mParams;
63b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
64b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private BridgeContext mContext;
65b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
66b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
67b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Creates a renderAction.
68b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p>
69b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * This <b>must</b> be followed by a call to {@link RenderAction#init()}, which act as a
70b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * call to {@link RenderAction#acquire(long)}
71b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
72b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param params the RenderParams. This must be a copy that the action can keep
73b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
74b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
75fd18f573280bbbcc549b35b548580a562bd960e2Xavier Ducrohet    protected RenderAction(T params) {
76b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mParams = params;
77b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
78b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
79b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
80b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
81b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * inflater, and parser.
82b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
83b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
84b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
85b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return whether the scene was prepared
86b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
87b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @see #acquire(long)
88b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @see #release()
89b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
90b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public Result init(long timeout) {
91b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
92b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // the result.
93b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Result result = acquireLock(timeout);
94b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (result != null) {
95b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return result;
96b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
97b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
98b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // setup the display Metrics.
99b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        DisplayMetrics metrics = new DisplayMetrics();
100b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.densityDpi = mParams.getDensity().getDpiValue();
1010a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
1020a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        metrics.density = metrics.noncompatDensity =
1030a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
1040a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
1050a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density;
1060a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
1070a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        metrics.widthPixels = metrics.noncompatWidthPixels = mParams.getScreenWidth();
1080a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        metrics.heightPixels = metrics.noncompatHeightPixels = mParams.getScreenHeight();
1090a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        metrics.xdpi = metrics.noncompatXdpi = mParams.getXdpi();
1100a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        metrics.ydpi = metrics.noncompatYdpi = mParams.getYdpi();
111b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
112b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        RenderResources resources = mParams.getResources();
113b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
114b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // build the context
115b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
1160a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion());
117b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
118b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        setUp();
119b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
120b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return SUCCESS.createResult();
121b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
122b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
1230a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
124b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
125b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Prepares the scene for action.
126b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p>
127b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * This call is blocking if another rendering/inflating is currently happening, and will return
128b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * whether the preparation worked.
129b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
130b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The preparation can fail if another rendering took too long and the timeout was elapsed.
131b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
132b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * More than one call to this from the same thread will have no effect and will return
133b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * {@link Result#SUCCESS}.
134b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
135b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * After scene actions have taken place, only one call to {@link #release()} must be
136b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * done.
137b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
138b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
139b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
140b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return whether the scene was prepared
141b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
142b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @see #release()
143b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
144b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @throws IllegalStateException if {@link #init(long)} was never called.
145b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
146b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public Result acquire(long timeout) {
147b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (mContext == null) {
148b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            throw new IllegalStateException("After scene creation, #init() must be called");
149b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
150b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
151b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
152b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // the result.
153b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Result result = acquireLock(timeout);
154b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (result != null) {
155b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return result;
156b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
157b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
158b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        setUp();
159b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
160b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return SUCCESS.createResult();
161b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
162b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
163b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
164b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Acquire the lock so that the scene can be acted upon.
165b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p>
166b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * This returns null if the lock was just acquired, otherwise it returns
167b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * {@link Result#SUCCESS} if the lock already belonged to that thread, or another
168b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * instance (see {@link Result#getStatus()}) if an error occurred.
169b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
170b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
171b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return null if the lock was just acquire or another result depending on the state.
172b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
173b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
174b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *      the scene.
175b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
176b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private Result acquireLock(long timeout) {
177b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        ReentrantLock lock = Bridge.getLock();
178b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (lock.isHeldByCurrentThread() == false) {
179b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            try {
180b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
181b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
182b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                if (acquired == false) {
183b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                    return ERROR_TIMEOUT.createResult();
184b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                }
185b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            } catch (InterruptedException e) {
186b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                return ERROR_LOCK_INTERRUPTED.createResult();
187b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            }
188b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        } else {
189b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            // This thread holds the lock already. Checks that this wasn't for a different context.
190b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            // If this is called by init, mContext will be null and so should sCurrentContext
191b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            // anyway
192b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            if (mContext != sCurrentContext) {
193b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                throw new IllegalStateException("Acquiring different scenes from same thread without releases");
194b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            }
195b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return SUCCESS.createResult();
196b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
197b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
198b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return null;
199b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
200b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
201b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
202b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Cleans up the scene after an action.
203b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
204b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public void release() {
205b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        ReentrantLock lock = Bridge.getLock();
206b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
207b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // with the use of finally blocks, it is possible to find ourself calling this
208b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // without a successful call to prepareScene. This test makes sure that unlock() will
209b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // not throw IllegalMonitorStateException.
210b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (lock.isHeldByCurrentThread()) {
211b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            tearDown();
212b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            lock.unlock();
213b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
214b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
215b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
216b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
217b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Sets up the session for rendering.
218b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p/>
219b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The counterpart is {@link #tearDown()}.
220b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
221b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private void setUp() {
222b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // make sure the Resources object references the context (and other objects) for this
223b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // scene
224b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.initResources();
225b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        sCurrentContext = mContext;
226b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
227b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        LayoutLog currentLog = mParams.getLog();
228b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Bridge.setLog(currentLog);
229b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setFrameworkResourceIdProvider(this);
230b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setLogger(currentLog);
231b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
232b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
233b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
234b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Tear down the session after rendering.
235b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p/>
236b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The counterpart is {@link #setUp()}.
237b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
238b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private void tearDown() {
239b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // Make sure to remove static references, otherwise we could not unload the lib
240b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.disposeResources();
241fb93ce9684120a36862b5b5e67b1865a652907e9Xavier Ducrohet
242fb93ce9684120a36862b5b5e67b1865a652907e9Xavier Ducrohet        // quit HandlerThread created during this session.
243fb93ce9684120a36862b5b5e67b1865a652907e9Xavier Ducrohet        HandlerThread_Delegate.cleanUp(sCurrentContext);
244fb93ce9684120a36862b5b5e67b1865a652907e9Xavier Ducrohet
2450a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        // clear the stored ViewConfiguration since the map is per density and not per context.
2460a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        ViewConfiguration.sConfigurations.clear();
2470a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
248b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        sCurrentContext = null;
249b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
250b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Bridge.setLog(null);
251b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setFrameworkResourceIdProvider(null);
252b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setLogger(null);
253b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
254b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
255b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public static BridgeContext getCurrentContext() {
256b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return sCurrentContext;
257b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
258b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
259b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    protected T getParams() {
260b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return mParams;
261b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
262b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
263b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    protected BridgeContext getContext() {
264b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return mContext;
265b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
266b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
267b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
268b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Returns the log associated with the session.
269b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return the log or null if there are none.
270b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
271b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public LayoutLog getLog() {
272b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (mParams != null) {
273b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return mParams.getLog();
274b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
275b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
276b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return null;
277b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
278b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
279b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
280b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Checks that the lock is owned by the current thread and that the current context is the one
281b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * from this scene.
282b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
283b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
284b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
285b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
286b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    protected void checkLock() {
287b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        ReentrantLock lock = Bridge.getLock();
288b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (lock.isHeldByCurrentThread() == false) {
289b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
290b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
291b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (sCurrentContext != mContext) {
292b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            throw new IllegalStateException("Thread acquired a scene but is rendering a different one");
293b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
294b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
295b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
2960a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet    private Configuration getConfiguration() {
2970a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        Configuration config = new Configuration();
2980a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
2990a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        ScreenSize screenSize = mParams.getConfigScreenSize();
3000a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        if (screenSize != null) {
3010a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet            switch (screenSize) {
3020a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                case SMALL:
3030a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL;
3040a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    break;
3050a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                case NORMAL:
3060a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL;
3070a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    break;
3080a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                case LARGE:
3090a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE;
3100a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    break;
3110a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                case XLARGE:
3120a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE;
3130a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet                    break;
3140a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet            }
3150a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        }
3160a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
3170a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        Density density = mParams.getDensity();
3180a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        if (density == null) {
3190a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet            density = Density.MEDIUM;
3200a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        }
3210a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
3220a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        config.screenWidthDp = mParams.getScreenWidth() / density.getDpiValue();
3230a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        config.screenHeightDp = mParams.getScreenHeight() / density.getDpiValue();
3240a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        if (config.screenHeightDp < config.screenWidthDp) {
3250a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet            config.smallestScreenWidthDp = config.screenHeightDp;
3260a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        } else {
3270a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet            config.smallestScreenWidthDp = config.screenWidthDp;
3280a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        }
3290a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
3300a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        // never run in compat mode:
3310a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        config.compatScreenWidthDp = config.screenWidthDp;
3320a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        config.compatScreenHeightDp = config.screenHeightDp;
3330a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
3340a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        // TODO: fill in more config info.
3350a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
3360a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet        return config;
3370a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet    }
3380a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
3390a49635b171f3ba366b1a7ebf28791c4661829bdXavier Ducrohet
340b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    // --- FrameworkResourceIdProvider methods
341b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
342b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    @Override
343b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public Integer getId(ResourceType resType, String resName) {
344b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return Bridge.getResourceId(resType, resName);
345b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
346b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet}
347