/** * Acquire the lock so that the scene can be acted upon. * * <p>This returns null if the lock was just acquired, otherwise it returns {@link * Result.Status#SUCCESS} if the lock already belonged to that thread, or another instance (see * {@link Result#getStatus()}) if an error occurred. * * @param timeout the time to wait if another rendering is happening. * @return null if the lock was just acquire or another result depending on the state. * @throws IllegalStateException if the current context is different than the one owned by the * scene. */ private Result acquireLock(long timeout) { ReentrantLock lock = Bridge.getLock(); if (!lock.isHeldByCurrentThread()) { try { boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); if (!acquired) { return ERROR_TIMEOUT.createResult(); } } catch (InterruptedException e) { return ERROR_LOCK_INTERRUPTED.createResult(); } } else { // This thread holds the lock already. Checks that this wasn't for a different context. // If this is called by init, mContext will be null and so should sCurrentContext // anyway if (mContext != sCurrentContext) { throw new IllegalStateException( "Acquiring different scenes from same thread without releases"); } return SUCCESS.createResult(); } return null; }
/** * Prepares the scene for action. * * <p>This call is blocking if another rendering/inflating is currently happening, and will return * whether the preparation worked. * * <p>The preparation can fail if another rendering took too long and the timeout was elapsed. * * <p>More than one call to this from the same thread will have no effect and will return {@link * Result.Status#SUCCESS}. * * <p>After scene actions have taken place, only one call to {@link #release()} must be done. * * @param timeout the time to wait if another rendering is happening. * @return whether the scene was prepared * @see #release() * @throws IllegalStateException if {@link #init(long)} was never called. */ public Result acquire(long timeout) { if (mContext == null) { throw new IllegalStateException("After scene creation, #init() must be called"); } // acquire the lock. if the result is null, lock was just acquired, otherwise, return // the result. Result result = acquireLock(timeout); if (result != null) { return result; } setUp(); return SUCCESS.createResult(); }
/** * Initializes and acquires the scene, creating various Android objects such as context, inflater, * and parser. * * @param timeout the time to wait if another rendering is happening. * @return whether the scene was prepared * @see #acquire(long) * @see #release() */ public Result init(long timeout) { // acquire the lock. if the result is null, lock was just acquired, otherwise, return // the result. Result result = acquireLock(timeout); if (result != null) { return result; } // setup the ParserFactory ParserFactory.setParserFactory(mParams.getLayoutlibCallback().getParserFactory()); HardwareConfig hardwareConfig = mParams.getHardwareConfig(); // setup the display Metrics. DisplayMetrics metrics = new DisplayMetrics(); metrics.densityDpi = metrics.noncompatDensityDpi = hardwareConfig.getDensity().getDpiValue(); metrics.density = metrics.noncompatDensity = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT; metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density; metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth(); metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight(); metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi(); metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi(); RenderResources resources = mParams.getResources(); // build the context mContext = new BridgeContext( mParams.getProjectKey(), metrics, resources, mParams.getAssets(), mParams.getLayoutlibCallback(), getConfiguration(), mParams.getTargetSdkVersion(), mParams.isRtlSupported()); setUp(); return SUCCESS.createResult(); }