1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2010 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage com.android.layoutlib.bridge.impl; 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.HardwareConfig; 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog; 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.RenderParams; 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.RenderResources; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider; 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.Result; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.Bridge; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.android.BridgeContext; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.Density; 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.ResourceType; 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.ScreenOrientation; 30295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Guptaimport com.android.resources.ScreenRound; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.ScreenSize; 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.res.Configuration; 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.os.HandlerThread_Delegate; 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.DisplayMetrics; 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.ViewConfiguration_Accessor; 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.inputmethod.InputMethodManager; 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.inputmethod.InputMethodManager_Accessor; 39b556decf75b2b084e1aed54ac7fa23a141eedb7fDeepanshu Guptaimport android.widget.SimpleMonthView_Delegate; 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4182c7fdb1f6346862de373c95c618e370f81d8df6Deepanshu Guptaimport java.util.Locale; 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.concurrent.TimeUnit; 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.concurrent.locks.ReentrantLock; 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4537dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED; 4637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT; 4737dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 4837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Base class for rendering action. 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * It provides life-cycle methods to init and stop the rendering. 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The most important methods are: 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * {@link #init(long)} and {@link #acquire(long)} to start a rendering and {@link #release()} 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * after the rendering. 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param <T> the {@link RenderParams} implementation 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic abstract class RenderAction<T extends RenderParams> extends FrameworkResourceIdProvider { 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The current context being rendered. This is set through {@link #acquire(long)} and 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * {@link #init(long)}, and unset in {@link #release()}. 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static BridgeContext sCurrentContext = null; 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final T mParams; 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private BridgeContext mContext; 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Creates a renderAction. 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p> 76d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta * This <b>must</b> be followed by a call to {@link RenderAction#init(long)}, which act as a 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * call to {@link RenderAction#acquire(long)} 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param params the RenderParams. This must be a copy that the action can keep 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski protected RenderAction(T params) { 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mParams = params; 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Initializes and acquires the scene, creating various Android objects such as context, 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * inflater, and parser. 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param timeout the time to wait if another rendering is happening. 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @return whether the scene was prepared 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see #acquire(long) 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see #release() 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Result init(long timeout) { 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // acquire the lock. if the result is null, lock was just acquired, otherwise, return 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the result. 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Result result = acquireLock(timeout); 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != null) { 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski HardwareConfig hardwareConfig = mParams.getHardwareConfig(); 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // setup the display Metrics. 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DisplayMetrics metrics = new DisplayMetrics(); 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.densityDpi = metrics.noncompatDensityDpi = 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hardwareConfig.getDensity().getDpiValue(); 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.density = metrics.noncompatDensity = 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT; 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density; 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth(); 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight(); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi(); 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi(); 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski RenderResources resources = mParams.getResources(); 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // build the context 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources, 12637dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta mParams.getAssets(), mParams.getLayoutlibCallback(), getConfiguration(), 127d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta mParams.getTargetSdkVersion(), mParams.isRtlSupported()); 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski setUp(); 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return SUCCESS.createResult(); 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Prepares the scene for action. 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p> 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This call is blocking if another rendering/inflating is currently happening, and will return 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * whether the preparation worked. 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The preparation can fail if another rendering took too long and the timeout was elapsed. 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * More than one call to this from the same thread will have no effect and will return 144d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta * {@link Result.Status#SUCCESS}. 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * After scene actions have taken place, only one call to {@link #release()} must be 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * done. 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param timeout the time to wait if another rendering is happening. 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @return whether the scene was prepared 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see #release() 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @throws IllegalStateException if {@link #init(long)} was never called. 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Result acquire(long timeout) { 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mContext == null) { 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new IllegalStateException("After scene creation, #init() must be called"); 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // acquire the lock. if the result is null, lock was just acquired, otherwise, return 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the result. 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Result result = acquireLock(timeout); 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (result != null) { 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski setUp(); 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return SUCCESS.createResult(); 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Acquire the lock so that the scene can be acted upon. 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p> 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This returns null if the lock was just acquired, otherwise it returns 178d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta * {@link Result.Status#SUCCESS} if the lock already belonged to that thread, or another 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * instance (see {@link Result#getStatus()}) if an error occurred. 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param timeout the time to wait if another rendering is happening. 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @return null if the lock was just acquire or another result depending on the state. 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @throws IllegalStateException if the current context is different than the one owned by 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * the scene. 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private Result acquireLock(long timeout) { 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ReentrantLock lock = Bridge.getLock(); 189d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta if (!lock.isHeldByCurrentThread()) { 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 193d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta if (!acquired) { 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return ERROR_TIMEOUT.createResult(); 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (InterruptedException e) { 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return ERROR_LOCK_INTERRUPTED.createResult(); 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This thread holds the lock already. Checks that this wasn't for a different context. 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this is called by init, mContext will be null and so should sCurrentContext 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // anyway 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mContext != sCurrentContext) { 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new IllegalStateException("Acquiring different scenes from same thread without releases"); 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return SUCCESS.createResult(); 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Cleans up the scene after an action. 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public void release() { 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ReentrantLock lock = Bridge.getLock(); 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // with the use of finally blocks, it is possible to find ourself calling this 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // without a successful call to prepareScene. This test makes sure that unlock() will 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // not throw IllegalMonitorStateException. 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (lock.isHeldByCurrentThread()) { 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tearDown(); 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski lock.unlock(); 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Sets up the session for rendering. 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The counterpart is {@link #tearDown()}. 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private void setUp() { 233996458b76c944f78eee26d7bd8cb4d39303b9119Deepanshu Gupta // setup the ParserFactory 234996458b76c944f78eee26d7bd8cb4d39303b9119Deepanshu Gupta ParserFactory.setParserFactory(mParams.getLayoutlibCallback().getParserFactory()); 235996458b76c944f78eee26d7bd8cb4d39303b9119Deepanshu Gupta 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // make sure the Resources object references the context (and other objects) for this 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // scene 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mContext.initResources(); 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sCurrentContext = mContext; 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // create an InputMethodManager 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski InputMethodManager.getInstance(); 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LayoutLog currentLog = mParams.getLog(); 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.setLog(currentLog); 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mContext.getRenderResources().setFrameworkResourceIdProvider(this); 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mContext.getRenderResources().setLogger(currentLog); 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Tear down the session after rendering. 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p/> 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The counterpart is {@link #setUp()}. 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private void tearDown() { 25603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // The context may be null, if there was an error during init(). 25703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (mContext != null) { 25803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // Make sure to remove static references, otherwise we could not unload the lib 25903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mContext.disposeResources(); 26003a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 26203a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (sCurrentContext != null) { 26303a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta // quit HandlerThread created during this session. 26403a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta HandlerThread_Delegate.cleanUp(sCurrentContext); 26503a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // clear the stored ViewConfiguration since the map is per density and not per context. 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ViewConfiguration_Accessor.clearConfigurations(); 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // remove the InputMethodManager 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski InputMethodManager_Accessor.resetInstance(); 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sCurrentContext = null; 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.setLog(null); 27603a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta if (mContext != null) { 27703a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mContext.getRenderResources().setFrameworkResourceIdProvider(null); 27803a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta mContext.getRenderResources().setLogger(null); 27903a057c1af9ca3f125c7924bf0b78da52223d8d3Deepanshu Gupta } 280f2d408b51debadca830eefbf8131185ac55ce699Deepanshu Gupta ParserFactory.setParserFactory(null); 281b556decf75b2b084e1aed54ac7fa23a141eedb7fDeepanshu Gupta SimpleMonthView_Delegate.clearCache(); 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static BridgeContext getCurrentContext() { 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return sCurrentContext; 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski protected T getParams() { 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mParams; 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski protected BridgeContext getContext() { 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mContext; 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns the log associated with the session. 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @return the log or null if there are none. 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public LayoutLog getLog() { 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mParams != null) { 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mParams.getLog(); 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Checks that the lock is owned by the current thread and that the current context is the one 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * from this scene. 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @throws IllegalStateException if the current context is different than the one owned by 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * the scene, or if {@link #acquire(long)} was not called. 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski protected void checkLock() { 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ReentrantLock lock = Bridge.getLock(); 317d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta if (!lock.isHeldByCurrentThread()) { 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (sCurrentContext != mContext) { 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new IllegalStateException("Thread acquired a scene but is rendering a different one"); 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private Configuration getConfiguration() { 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Configuration config = new Configuration(); 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski HardwareConfig hardwareConfig = mParams.getHardwareConfig(); 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ScreenSize screenSize = hardwareConfig.getScreenSize(); 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (screenSize != null) { 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch (screenSize) { 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case SMALL: 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL; 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case NORMAL: 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL; 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case LARGE: 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE; 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case XLARGE: 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE; 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Density density = hardwareConfig.getDensity(); 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (density == null) { 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski density = Density.MEDIUM; 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue(); 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue(); 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (config.screenHeightDp < config.screenWidthDp) { 356d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta //noinspection SuspiciousNameCombination 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = config.screenHeightDp; 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.smallestScreenWidthDp = config.screenWidthDp; 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.densityDpi = density.getDpiValue(); 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // never run in compat mode: 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.compatScreenWidthDp = config.screenWidthDp; 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.compatScreenHeightDp = config.screenHeightDp; 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ScreenOrientation orientation = hardwareConfig.getOrientation(); 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (orientation != null) { 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch (orientation) { 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case PORTRAIT: 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = Configuration.ORIENTATION_PORTRAIT; 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case LANDSCAPE: 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = Configuration.ORIENTATION_LANDSCAPE; 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case SQUARE: 377d51834bdfad0cd3142ac464ab3a3b0db14f884c3Deepanshu Gupta //noinspection deprecation 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = Configuration.ORIENTATION_SQUARE; 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.orientation = Configuration.ORIENTATION_UNDEFINED; 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 385295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta try { 386295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta ScreenRound roundness = hardwareConfig.getScreenRoundness(); 387295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta if (roundness != null) { 388295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta switch (roundness) { 389295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta case ROUND: 390295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES; 391295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta break; 392295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta case NOTROUND: 393295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_NO; 394295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta } 395295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta } else { 396295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_UNDEFINED; 397295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta } 398295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta } catch (NoSuchMethodError ignored) { 399295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta // getScreenRoundness was added in later stages of API 15. So, it's not present on some 400295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta // preview releases of API 15. 401295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta // TODO: Remove the try catch around Oct 2015. 402295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta } 40382c7fdb1f6346862de373c95c618e370f81d8df6Deepanshu Gupta String locale = getParams().getLocale(); 40482c7fdb1f6346862de373c95c618e370f81d8df6Deepanshu Gupta if (locale != null && !locale.isEmpty()) config.locale = new Locale(locale); 405295ef6be084d1c2f22ef25a87e508c1f5c14ee5aDeepanshu Gupta 406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // TODO: fill in more config info. 407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return config; 409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // --- FrameworkResourceIdProvider methods 413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Integer getId(ResourceType resType, String resName) { 416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Bridge.getResourceId(resType, resName); 417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 419