RenderAction.java revision b0d34f9c99cbd43e8238c5952b19d032f02dd168
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;
30b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport com.android.resources.ResourceType;
31b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
32b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport android.util.DisplayMetrics;
33b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
34b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport java.util.concurrent.TimeUnit;
35b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetimport java.util.concurrent.locks.ReentrantLock;
36b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
37b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet/**
38b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * Class implementing the render session.
39b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
40b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming
41b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
42b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * be done on the layout.
43b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
44b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet * @param <T> the {@link RenderParams} implementation
45b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet *
46b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet */
47b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderAction<T extends RenderParams> extends FrameworkResourceIdProvider {
48b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
49b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
50b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The current context being rendered. This is set through {@link #acquire(long)} and
51b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * {@link #init(long)}, and unset in {@link #release()}.
52b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
53b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private static BridgeContext sCurrentContext = null;
54b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
55b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private final T mParams;
56b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
57b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private BridgeContext mContext;
58b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
59b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
60b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Creates a renderAction.
61b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p>
62b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * This <b>must</b> be followed by a call to {@link RenderAction#init()}, which act as a
63b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * call to {@link RenderAction#acquire(long)}
64b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
65b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param params the RenderParams. This must be a copy that the action can keep
66b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
67b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
68b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public RenderAction(T params) {
69b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mParams = params;
70b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
71b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
72b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
73b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
74b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * inflater, and parser.
75b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
76b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
77b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
78b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return whether the scene was prepared
79b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
80b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @see #acquire(long)
81b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @see #release()
82b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
83b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public Result init(long timeout) {
84b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
85b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // the result.
86b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Result result = acquireLock(timeout);
87b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (result != null) {
88b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return result;
89b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
90b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
91b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // setup the display Metrics.
92b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        DisplayMetrics metrics = new DisplayMetrics();
93b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.densityDpi = mParams.getDensity().getDpiValue();
94b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.density = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
95b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.scaledDensity = metrics.density;
96b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.widthPixels = mParams.getScreenWidth();
97b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.heightPixels = mParams.getScreenHeight();
98b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.xdpi = mParams.getXdpi();
99b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        metrics.ydpi = mParams.getYdpi();
100b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
101b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        RenderResources resources = mParams.getResources();
102b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
103b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // build the context
104b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
105b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                mParams.getProjectCallback(), mParams.getTargetSdkVersion());
106b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
107b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        setUp();
108b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
109b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return SUCCESS.createResult();
110b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
111b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
112b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
113b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Prepares the scene for action.
114b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p>
115b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * This call is blocking if another rendering/inflating is currently happening, and will return
116b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * whether the preparation worked.
117b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
118b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The preparation can fail if another rendering took too long and the timeout was elapsed.
119b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
120b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * More than one call to this from the same thread will have no effect and will return
121b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * {@link Result#SUCCESS}.
122b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
123b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * After scene actions have taken place, only one call to {@link #release()} must be
124b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * done.
125b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
126b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
127b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
128b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return whether the scene was prepared
129b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
130b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @see #release()
131b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
132b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @throws IllegalStateException if {@link #init(long)} was never called.
133b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
134b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public Result acquire(long timeout) {
135b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (mContext == null) {
136b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            throw new IllegalStateException("After scene creation, #init() must be called");
137b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
138b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
139b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
140b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // the result.
141b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Result result = acquireLock(timeout);
142b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (result != null) {
143b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return result;
144b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
145b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
146b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        setUp();
147b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
148b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return SUCCESS.createResult();
149b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
150b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
151b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
152b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Acquire the lock so that the scene can be acted upon.
153b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p>
154b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * This returns null if the lock was just acquired, otherwise it returns
155b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * {@link Result#SUCCESS} if the lock already belonged to that thread, or another
156b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * instance (see {@link Result#getStatus()}) if an error occurred.
157b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
158b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
159b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return null if the lock was just acquire or another result depending on the state.
160b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
161b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
162b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *      the scene.
163b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
164b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private Result acquireLock(long timeout) {
165b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        ReentrantLock lock = Bridge.getLock();
166b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (lock.isHeldByCurrentThread() == false) {
167b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            try {
168b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
169b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
170b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                if (acquired == false) {
171b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                    return ERROR_TIMEOUT.createResult();
172b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                }
173b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            } catch (InterruptedException e) {
174b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                return ERROR_LOCK_INTERRUPTED.createResult();
175b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            }
176b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        } else {
177b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            // This thread holds the lock already. Checks that this wasn't for a different context.
178b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            // If this is called by init, mContext will be null and so should sCurrentContext
179b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            // anyway
180b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            if (mContext != sCurrentContext) {
181b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                throw new IllegalStateException("Acquiring different scenes from same thread without releases");
182b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            }
183b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return SUCCESS.createResult();
184b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
185b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
186b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return null;
187b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
188b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
189b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
190b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Cleans up the scene after an action.
191b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
192b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public void release() {
193b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        ReentrantLock lock = Bridge.getLock();
194b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
195b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // with the use of finally blocks, it is possible to find ourself calling this
196b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // without a successful call to prepareScene. This test makes sure that unlock() will
197b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // not throw IllegalMonitorStateException.
198b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (lock.isHeldByCurrentThread()) {
199b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            tearDown();
200b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            lock.unlock();
201b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
202b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
203b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
204b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
205b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Sets up the session for rendering.
206b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p/>
207b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The counterpart is {@link #tearDown()}.
208b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
209b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private void setUp() {
210b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // make sure the Resources object references the context (and other objects) for this
211b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // scene
212b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.initResources();
213b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        sCurrentContext = mContext;
214b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
215b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        LayoutLog currentLog = mParams.getLog();
216b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Bridge.setLog(currentLog);
217b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setFrameworkResourceIdProvider(this);
218b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setLogger(currentLog);
219b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
220b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
221b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
222b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Tear down the session after rendering.
223b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * <p/>
224b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * The counterpart is {@link #setUp()}.
225b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
226b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    private void tearDown() {
227b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        // Make sure to remove static references, otherwise we could not unload the lib
228b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.disposeResources();
229b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        sCurrentContext = null;
230b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
231b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Bridge.setLog(null);
232b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setFrameworkResourceIdProvider(null);
233b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mContext.getRenderResources().setLogger(null);
234b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
235b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
236b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public static BridgeContext getCurrentContext() {
237b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return sCurrentContext;
238b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
239b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
240b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    protected T getParams() {
241b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return mParams;
242b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
243b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
244b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    protected BridgeContext getContext() {
245b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return mContext;
246b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
247b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
248b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
249b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Returns the log associated with the session.
250b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @return the log or null if there are none.
251b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
252b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public LayoutLog getLog() {
253b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (mParams != null) {
254b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            return mParams.getLog();
255b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
256b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
257b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return null;
258b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
259b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
260b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    /**
261b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * Checks that the lock is owned by the current thread and that the current context is the one
262b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * from this scene.
263b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *
264b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
265b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
266b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet     */
267b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    protected void checkLock() {
268b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        ReentrantLock lock = Bridge.getLock();
269b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (lock.isHeldByCurrentThread() == false) {
270b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
271b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
272b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (sCurrentContext != mContext) {
273b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            throw new IllegalStateException("Thread acquired a scene but is rendering a different one");
274b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        }
275b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
276b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
277b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    // --- FrameworkResourceIdProvider methods
278b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
279b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    @Override
280b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    public Integer getId(ResourceType resType, String resName) {
281b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return Bridge.getResourceId(resType, resName);
282b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    }
283b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet}
284