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