Snap for 11566117 from 079b068bc74a02f8f38fc9831337fe59827e7f48 to sdk-release

Change-Id: Icb5812ccd75fd2b0d8549255bb2135291bc31a7b
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0a1e4e0..d47ec03 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -53,7 +53,7 @@
       </value>
     </option>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
 </project>
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 76bc916..5fd342d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,7 +30,7 @@
     tools: ["layoutlib_create"],
     out: ["temp_layoutlib.jar"],
     srcs: [
-        ":atf-prebuilt-502584086{.jar}",
+        ":atf-prebuilt-557133692{.jar}",
         ":core-icu4j-for-host{.jar}",
         ":core-libart-for-host{.jar}",
         ":framework-all{.jar}",
diff --git a/bridge/bridge_client/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java b/bridge/bridge_client/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java
index 35ade34..c0e22d3 100644
--- a/bridge/bridge_client/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java
+++ b/bridge/bridge_client/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java
@@ -56,6 +56,7 @@
     private LayoutlibCallback mLayoutlibCallback;
     private int mTargetSdk;
     private int mMinSdk = 0;
+    private int mSimulatedSdk = 0;
     private ILayoutLog mLayoutLog;
     private Map<SessionParams.Key, Object> mFlags = new HashMap<>();
     private AssetRepository mAssetRepository = null;
@@ -135,6 +136,12 @@
     }
 
     @NonNull
+    public SessionParamsBuilder setSimulatedSdk(int simulatedSdk) {
+        mSimulatedSdk = simulatedSdk;
+        return this;
+    }
+
+    @NonNull
     public SessionParamsBuilder setLayoutLog(@NonNull ILayoutLog layoutLog) {
         mLayoutLog = layoutLog;
         return this;
@@ -202,7 +209,7 @@
 
         SessionParams params = new SessionParams(mLayoutParser, mRenderingMode, mProjectKey /* for
         caching */, mConfigGenerator.getHardwareConfig(), resourceResolver, mLayoutlibCallback,
-                mMinSdk, mTargetSdk, mLayoutLog);
+                mMinSdk, mTargetSdk, mLayoutLog, mSimulatedSdk);
         params.setFlag(RenderParamsFlags.FLAG_ENABLE_LAYOUT_VALIDATOR, enableLayoutValidator);
         params.setFlag(
                 RenderParamsFlags.FLAG_ENABLE_LAYOUT_VALIDATOR_IMAGE_CHECK,
diff --git a/bridge/src/android/content/res/BridgeTypedArray.java b/bridge/src/android/content/res/BridgeTypedArray.java
index da59fb7..ae6f538 100644
--- a/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/bridge/src/android/content/res/BridgeTypedArray.java
@@ -907,7 +907,7 @@
             boolean found = false;
 
             String value = mResourceData[index].getValue();
-            if (!value.isEmpty()) {
+            if (value != null && !value.isEmpty()) {
                 // Check if the value string is already representing an integer and return it if so.
                 // Resources coming from res.apk in an AAR may have flags and enums in integer form.
                 char c = value.charAt(0);
diff --git a/bridge/src/android/content/res/Resources_Delegate.java b/bridge/src/android/content/res/Resources_Delegate.java
index 7aa02f9..4eb6bdd 100644
--- a/bridge/src/android/content/res/Resources_Delegate.java
+++ b/bridge/src/android/content/res/Resources_Delegate.java
@@ -87,6 +87,8 @@
                 "Resources_Delegate.initSystem called twice before disposeSystem was called";
         Resources resources = new Resources(Resources_Delegate.class.getClassLoader());
         resources.setImpl(new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()));
+        resources.getConfiguration().windowConfiguration.setMaxBounds(0, 0, metrics.widthPixels,
+                metrics.heightPixels);
         sContexts.put(resources, Objects.requireNonNull(context));
         sLayoutlibCallbacks.put(resources, Objects.requireNonNull(layoutlibCallback));
         return Resources.mSystem = resources;
diff --git a/bridge/src/android/os/NullVibratorManager.java b/bridge/src/android/os/NullVibratorManager.java
new file mode 100644
index 0000000..fe269c7
--- /dev/null
+++ b/bridge/src/android/os/NullVibratorManager.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+public class NullVibratorManager extends VibratorManager {
+    private static final NullVibratorManager sInstance = new NullVibratorManager();
+
+    public static NullVibratorManager getInstance() {
+        return sInstance;
+    }
+
+    private NullVibratorManager() { }
+
+    @Override
+    public int[] getVibratorIds() {
+        return new int[0];
+    }
+
+    @Override
+    public Vibrator getVibrator(int vibratorId) {
+        return NullVibrator.getInstance();
+    }
+
+    @Override
+    public Vibrator getDefaultVibrator() {
+        return NullVibrator.getInstance();
+    }
+
+    @Override
+    public void vibrate(int uid, String opPkg, CombinedVibration effect, String reason,
+            VibrationAttributes attributes) { }
+
+    @Override
+    public void cancel() { }
+
+    @Override
+    public void cancel(int usageFilter) { }
+}
diff --git a/bridge/src/android/permission/PermissionManager_Delegate.java b/bridge/src/android/permission/PermissionManager_Delegate.java
index 1aad830..642b015 100644
--- a/bridge/src/android/permission/PermissionManager_Delegate.java
+++ b/bridge/src/android/permission/PermissionManager_Delegate.java
@@ -23,7 +23,7 @@
 public class PermissionManager_Delegate {
 
     @LayoutlibDelegate
-    public static int checkPermission(String permission, int pid, int uid) {
+    public static int checkPermission(String permission, int pid, int uid, int deviceId) {
         return PackageManager.PERMISSION_GRANTED;
     }
 }
diff --git a/bridge/src/android/provider/Settings_Config_Delegate.java b/bridge/src/android/provider/Settings_Config_Delegate.java
new file mode 100644
index 0000000..ae802dd
--- /dev/null
+++ b/bridge/src/android/provider/Settings_Config_Delegate.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider;
+
+import com.android.layoutlib.bridge.impl.RenderAction;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.ContentResolver;
+
+/**
+ * Delegate that provides alternative implementation for methods in {@link Settings.Config}
+ * <p/>
+ * Through the layoutlib_create tool, selected methods of DeviceConfig have been replaced by
+ * calls to methods of the same name in this delegate class.
+ */
+public class Settings_Config_Delegate {
+    @LayoutlibDelegate
+    static ContentResolver getContentResolver() {
+        return RenderAction.getCurrentContext().getContentResolver();
+    }
+}
diff --git a/bridge/src/android/util/BridgeXmlPullAttributes.java b/bridge/src/android/util/BridgeXmlPullAttributes.java
index 8a78fa3..07bc437 100644
--- a/bridge/src/android/util/BridgeXmlPullAttributes.java
+++ b/bridge/src/android/util/BridgeXmlPullAttributes.java
@@ -151,6 +151,9 @@
     @Override
     public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
         String value = getAttributeValue(namespace, attribute);
+        if (value == null) {
+            return defaultValue;
+        }
 
         return resolveResourceValue(value, defaultValue);
     }
diff --git a/bridge/src/android/view/AttachInfo_Accessor.java b/bridge/src/android/view/AttachInfo_Accessor.java
index cd35899..b8c8f0e 100644
--- a/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/bridge/src/android/view/AttachInfo_Accessor.java
@@ -37,6 +37,8 @@
         info.mInTouchMode = false; // this is so that we can display selections.
         info.mHardwareAccelerated = false;
         info.mApplicationScale = 1.0f;
+        ViewRootImpl_Accessor.setChild(root, view);
+        view.assignParent(root);
         view.dispatchAttachedToWindow(info, 0);
     }
 
@@ -46,7 +48,11 @@
 
     public static void detachFromWindow(final View view) {
         if (view != null) {
+            final View.AttachInfo attachInfo = view.mAttachInfo;
             view.dispatchDetachedFromWindow();
+            if (attachInfo != null) {
+                ViewRootImpl_Accessor.detachFromWindow(attachInfo.mViewRootImpl);
+            }
         }
     }
 
diff --git a/bridge/src/android/view/BridgeInflater.java b/bridge/src/android/view/BridgeInflater.java
index ec8476d..ad9a442 100644
--- a/bridge/src/android/view/BridgeInflater.java
+++ b/bridge/src/android/view/BridgeInflater.java
@@ -250,6 +250,9 @@
      */
     @Nullable
     private View createViewFromCustomInflater(@NotNull String name, @NotNull AttributeSet attrs) {
+        if (!mLayoutlibCallback.shouldUseCustomInflater()) {
+            return null;
+        }
         if (mCustomInflater == null) {
             Context context = getContext();
             context = getBaseContext(context);
diff --git a/bridge/src/android/view/DisplayEventReceiver_Delegate.java b/bridge/src/android/view/DisplayEventReceiver_Delegate.java
index f1d4e65..0ca568c 100644
--- a/bridge/src/android/view/DisplayEventReceiver_Delegate.java
+++ b/bridge/src/android/view/DisplayEventReceiver_Delegate.java
@@ -20,6 +20,7 @@
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
 import android.os.MessageQueue;
+import android.view.DisplayEventReceiver.VsyncEventData;
 
 import java.lang.ref.WeakReference;
 
@@ -32,7 +33,8 @@
 
     @LayoutlibDelegate
     /*package*/ static long nativeInit(WeakReference<DisplayEventReceiver> receiver,
-            MessageQueue messageQueue, int vsyncSource, int eventRegistration, long layerHandle) {
+            WeakReference<VsyncEventData> vsyncEventData, MessageQueue messageQueue,
+            int vsyncSource, int eventRegistration, long layerHandle) {
         return sManager.addNewDelegate(new DisplayEventReceiver_Delegate());
     }
 
diff --git a/bridge/src/android/view/LayoutInflater_Delegate.java b/bridge/src/android/view/LayoutInflater_Delegate.java
index cb446e7..51c413d 100644
--- a/bridge/src/android/view/LayoutInflater_Delegate.java
+++ b/bridge/src/android/view/LayoutInflater_Delegate.java
@@ -233,15 +233,4 @@
 
         LayoutInflater.consumeChildElements(parser);
     }
-
-    @LayoutlibDelegate
-    /* package */ static void initPrecompiledViews(LayoutInflater thisInflater) {
-        initPrecompiledViews(thisInflater, false);
-    }
-
-    @LayoutlibDelegate
-    /* package */ static void initPrecompiledViews(LayoutInflater thisInflater,
-            boolean enablePrecompiledViews) {
-        thisInflater.initPrecompiledViews_Original(enablePrecompiledViews);
-    }
 }
diff --git a/bridge/src/android/view/SurfaceView.java b/bridge/src/android/view/SurfaceView.java
index ebb2af4..2c1d674 100644
--- a/bridge/src/android/view/SurfaceView.java
+++ b/bridge/src/android/view/SurfaceView.java
@@ -18,11 +18,17 @@
 
 import com.android.layoutlib.bridge.MockView;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.os.IBinder;
 import android.util.AttributeSet;
+import android.view.SurfaceControl.Transaction;
+
+import java.util.function.Consumer;
 
 /**
  * Mock version of the SurfaceView.
@@ -50,6 +56,11 @@
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
+    public SurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes, boolean disableBackgroundLayer) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
     public boolean gatherTransparentRegion(Region region) {
       return false;
     }
@@ -60,6 +71,14 @@
     public void setZOrderOnTop(boolean onTop) {
     }
 
+    public boolean isZOrderedOnTop() {
+        return false;
+    }
+
+    public boolean setZOrderedOnTop(boolean onTop, boolean allowDynamicChange) {
+        return true;
+    }
+
     public void setSecure(boolean isSecure) {
     }
 
@@ -67,6 +86,60 @@
         return mSurfaceHolder;
     }
 
+    public void setUseAlpha() {
+    }
+
+    public void setEnableSurfaceClipping(boolean enabled) {
+    }
+
+    public void setCornerRadius(float cornerRadius) {
+    }
+
+    public float getCornerRadius() {
+        return 0;
+    }
+
+    public void setSurfaceLifecycle(int lifecycleStrategy) {
+    }
+
+    public String getName() {
+        return "MockSurfaceView";
+    }
+
+    public void requestUpdateSurfacePositionAndScale() {
+    }
+
+    public @NonNull Rect getSurfaceRenderPosition() {
+        return new Rect();
+    }
+
+    public boolean isFixedSize() {
+        return true;
+    }
+
+    public void setResizeBackgroundColor(int bgColor) {
+    }
+
+    public void setResizeBackgroundColor(@NonNull SurfaceControl.Transaction t, int bgColor) {
+    }
+
+    public SurfaceControl getSurfaceControl() {
+        return null;
+    }
+
+    public @Nullable IBinder getHostToken() {
+        return null;
+    }
+
+    public void setChildSurfacePackage(@NonNull SurfaceControlViewHost.SurfacePackage p) {
+    }
+
+    public void syncNextFrame(Consumer<Transaction> t) {
+    }
+
+    public void applyTransactionToFrame(@NonNull SurfaceControl.Transaction transaction) {
+    }
+
     private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
 
         @Override
diff --git a/bridge/src/android/view/ViewRootImpl_Accessor.java b/bridge/src/android/view/ViewRootImpl_Accessor.java
index 81ffe2e..d15952a 100644
--- a/bridge/src/android/view/ViewRootImpl_Accessor.java
+++ b/bridge/src/android/view/ViewRootImpl_Accessor.java
@@ -26,8 +26,17 @@
 
     public static void setChild(ViewRootImpl viewRoot, View child) {
         viewRoot.mView = child;
-        child.assignParent(viewRoot);
-        viewRoot.mWidth = child.getWidth();
-        viewRoot.mHeight = child.getHeight();
+        if (child != null) {
+            viewRoot.mWidth = child.getWidth();
+            viewRoot.mHeight = child.getHeight();
+        } else {
+            viewRoot.mWidth = -1;
+            viewRoot.mHeight = -1;
+        }
+    }
+
+    public static void detachFromWindow(ViewRootImpl viewRoot) {
+        viewRoot.mAccessibilityInteractionConnectionManager.ensureNoConnection();
+        viewRoot.mAccessibilityInteractionConnectionManager.ensureNoDirectConnection();
     }
 }
diff --git a/bridge/src/android/view/WindowManagerImpl.java b/bridge/src/android/view/WindowManagerImpl.java
index eb1e22c..285ca9e 100644
--- a/bridge/src/android/view/WindowManagerImpl.java
+++ b/bridge/src/android/view/WindowManagerImpl.java
@@ -41,6 +41,8 @@
 import com.android.internal.policy.DecorView;
 import com.android.layoutlib.bridge.Bridge;
 
+import java.util.ArrayList;
+
 public class WindowManagerImpl implements WindowManager {
 
     private final Context mContext;
@@ -179,10 +181,12 @@
             }
         }
         mCurrentRootView.addView(arg0, frameLayoutParams);
+        ViewRootImpl_Accessor.setChild(mBaseRootView.getViewRootImpl(), arg0);
     }
 
     @Override
     public void removeView(View arg0) {
+        ViewRootImpl viewRootImpl = arg0.getViewRootImpl();
         if (mCurrentRootView != null) {
             mCurrentRootView.removeView(arg0);
             if (mBaseRootView != null && mCurrentRootView.getChildCount() == 0) {
@@ -190,6 +194,20 @@
                 mCurrentRootView = null;
             }
         }
+        if (viewRootImpl != null && viewRootImpl.getView() == arg0) {
+            View newRoot = null;
+            if (mCurrentRootView != null && mCurrentRootView.getChildCount() > 0) {
+                ArrayList<View> childrenList = mCurrentRootView.buildOrderedChildList();
+                newRoot = childrenList.get(childrenList.size() - 1);
+            } else if (mBaseRootView != null) {
+                View root = mBaseRootView;
+                while (root.getParent() instanceof View) {
+                    root = (View)root.getParent();
+                }
+                newRoot = root;
+            }
+            ViewRootImpl_Accessor.setChild(viewRootImpl, newRoot);
+        }
     }
 
     @Override
diff --git a/bridge/src/android/view/accessibility/AccessibilityInteractionClient_Accessor.java b/bridge/src/android/view/accessibility/AccessibilityInteractionClient_Accessor.java
new file mode 100644
index 0000000..8c87c22
--- /dev/null
+++ b/bridge/src/android/view/accessibility/AccessibilityInteractionClient_Accessor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility;
+
+public class AccessibilityInteractionClient_Accessor {
+    public static void clearCaches() {
+        AccessibilityInteractionClient.sCaches.clear();
+        AccessibilityInteractionClient.sClients.clear();
+        AccessibilityInteractionClient.sConnectionCache.clear();
+        AccessibilityInteractionClient.sScrollingWindows.clear();
+        AccessibilityInteractionClient.sDirectConnectionCount = 0;
+    }
+}
diff --git a/bridge/src/android/view/accessibility/AccessibilityManager_Delegate.java b/bridge/src/android/view/accessibility/AccessibilityManager_Delegate.java
new file mode 100644
index 0000000..9408f79
--- /dev/null
+++ b/bridge/src/android/view/accessibility/AccessibilityManager_Delegate.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility;
+
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.view.MagnificationSpec;
+import android.view.accessibility.IAccessibilityManager.WindowTransformationSpec;
+
+public class AccessibilityManager_Delegate {
+    private static WindowTransformationSpec sInstance;
+
+    @LayoutlibDelegate
+    public static IAccessibilityManager.WindowTransformationSpec getWindowTransformationSpec(
+            AccessibilityManager thisManager, int windowId) {
+        if (sInstance == null) {
+            WindowTransformationSpec spec = new WindowTransformationSpec();
+            spec.magnificationSpec = new MagnificationSpec();
+            float[] matrix = new float[9];
+            Matrix.IDENTITY_MATRIX.getValues(matrix);
+            spec.transformationMatrix = matrix;
+            sInstance = spec;
+        }
+        return sInstance;
+    }
+
+    @LayoutlibDelegate
+    public static AccessibilityManager getInstance(Context context) {
+        Context baseContext = BridgeContext.getBaseContext(context);
+        return ((BridgeContext)baseContext).getAccessibilityManager();
+    }
+}
diff --git a/bridge/src/com/android/layoutlib/bridge/Bridge.java b/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 3c62193..ce0fb2d 100644
--- a/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -337,7 +337,7 @@
     }
 
     /**
-     * Tests if the field is pubic, static and one of int or int[].
+     * Tests if the field is public, static and one of int or int[].
      */
     private static boolean isValidRField(Field field) {
         int modifiers = field.getModifiers();
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index a0cf2b2..9bffc23 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -40,6 +40,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.animation.AnimationHandler;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -81,6 +82,8 @@
 import android.os.IBinder;
 import android.os.IInterface;
 import android.os.Looper;
+import android.os.NullVibrator;
+import android.os.NullVibratorManager;
 import android.os.Parcel;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -170,7 +173,7 @@
     private final LayoutlibCallback mLayoutlibCallback;
     private final WindowManager mWindowManager;
     private final DisplayManager mDisplayManager;
-    private final AutofillManager mAutofillManager;
+    private AutofillManager mAutofillManager;
     private final ClipboardManager mClipboardManager;
     private final ActivityManager mActivityManager;
     private final ConnectivityManager mConnectivityManager;
@@ -199,10 +202,12 @@
     private Boolean mIsThemeAppCompat;
     private boolean mUseThemedIcon;
     private Context mApplicationContext;
+    private AccessibilityManager mAccessibilityManager;
     private final ResourceNamespace mAppCompatNamespace;
     private final Map<Key<?>, Object> mUserData = new HashMap<>();
 
     private final SessionInteractiveData mSessionInteractiveData;
+    private final ThreadLocal<AnimationHandler> mAnimationHandlerThreadLocal = new ThreadLocal<>();
 
     /**
      * Some applications that target both pre API 17 and post API 17, set the newer attrs to
@@ -263,7 +268,6 @@
 
         mWindowManager = new WindowManagerImpl(this, mMetrics);
         mDisplayManager = new DisplayManager(this);
-        mAutofillManager = new AutofillManager(this, new Default());
         mClipboardManager = new ClipboardManager(this, null);
         mActivityManager = ActivityManager_Accessor.getActivityManagerInstance(this);
         mConnectivityManager = new ConnectivityManager(this, null);
@@ -462,9 +466,12 @@
                 try {
                     outValue.data = Integer.parseInt(stringValue);
                     outValue.type = TypedValue.TYPE_INT_DEC;
-                } catch (NumberFormatException e) {
-                    outValue.type = TypedValue.TYPE_STRING;
-                    outValue.string = stringValue;
+                }
+                catch (NumberFormatException e) {
+                    if (!ResourceHelper.parseFloatAttribute(null, stringValue, outValue, false)) {
+                        outValue.type = TypedValue.TYPE_STRING;
+                        outValue.string = stringValue;
+                    }
                 }
             }
         }
@@ -601,6 +608,13 @@
         return isThemeAppCompat;
     }
 
+    public AccessibilityManager getAccessibilityManager() {
+        if (mAccessibilityManager == null) {
+            mAccessibilityManager = new AccessibilityManager(this, null, UserHandle.USER_CURRENT);
+        }
+        return mAccessibilityManager;
+    }
+
     // ------------ Context methods
 
     @Override
@@ -673,6 +687,9 @@
                 return InputMethodManager.forContext(this);
 
             case AUTOFILL_MANAGER_SERVICE:
+                if (mAutofillManager == null) {
+                    mAutofillManager = new AutofillManager(this, new Default());
+                }
                 return mAutofillManager;
 
             case CLIPBOARD_SERVICE:
@@ -690,6 +707,12 @@
             case INPUT_SERVICE:
                 return mInputManager;
 
+            case VIBRATOR_SERVICE:
+                return NullVibrator.getInstance();
+
+            case VIBRATOR_MANAGER_SERVICE:
+                return NullVibratorManager.getInstance();
+
             case TEXT_CLASSIFICATION_SERVICE:
             case CONTENT_CAPTURE_MANAGER_SERVICE:
             case ALARM_SERVICE:
@@ -1525,7 +1548,7 @@
     @Override
     public ContentResolver getContentResolver() {
         if (mContentResolver == null) {
-            mContentResolver = new BridgeContentResolver(this);
+            mContentResolver = new BridgeContentResolver(getApplicationContext());
         }
         return mContentResolver;
     }
@@ -2289,4 +2312,9 @@
     public void applyWallpaper(String wallpaperPath) {
         mRenderResources.setWallpaper(wallpaperPath, mConfig.isNightModeActive());
     }
+
+    @NotNull
+    public ThreadLocal<AnimationHandler> getAnimationHandlerThreadLocal() {
+        return mAnimationHandlerThreadLocal;
+    }
 }
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 85bf637..c376429 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -61,6 +61,11 @@
     }
 
     @Override
+    public boolean isBatterySaverSupported() throws RemoteException {
+        return true;
+    }
+
+    @Override
     public BatterySaverPolicyConfig getFullPowerSavePolicy() {
         return new BatterySaverPolicyConfig.Builder().build();
     }
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeThermalService.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeThermalService.java
index 5fe116e..0122da1 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeThermalService.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeThermalService.java
@@ -90,4 +90,9 @@
     public float getThermalHeadroom(int forecastSeconds) {
         return Float.NaN;
     }
+
+    @Override
+    public float[] getThermalHeadroomThresholds() {
+        return new float[]{};
+    }
 }
diff --git a/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/bridge/src/com/android/layoutlib/bridge/bars/Config.java
index d89960e..7949908 100644
--- a/bridge/src/com/android/layoutlib/bridge/bars/Config.java
+++ b/bridge/src/com/android/layoutlib/bridge/bars/Config.java
@@ -92,8 +92,8 @@
     }
 
     public static String getTime(int platformVersion) {
-        if (isGreaterOrEqual(platformVersion, TIRAMISU)) {
-            return "13:00";
+        if (isGreaterOrEqual(platformVersion, UPSIDE_DOWN_CAKE)) {
+            return "14:00";
         }
         if (platformVersion < GINGERBREAD) {
             return "2:20";
@@ -143,6 +143,9 @@
         if (platformVersion < TIRAMISU) {
             return "12:00";
         }
+        if (platformVersion < UPSIDE_DOWN_CAKE) {
+            return "13:00";
+        }
         // Should never happen.
         return "4:04";
     }
diff --git a/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 63efec3..98378e6 100644
--- a/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -24,18 +24,13 @@
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.layoutlib.bridge.resources.IconLoader;
 import com.android.layoutlib.bridge.resources.SysUiResources;
 import com.android.resources.Density;
-import com.android.resources.LayoutDirection;
 import com.android.resources.ResourceType;
 
 import android.annotation.NonNull;
 import android.content.res.ColorStateList;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapFactory.Options;
-import android.graphics.drawable.BitmapDrawable;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.util.TypedValue;
 import android.view.Gravity;
@@ -45,12 +40,10 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import java.io.InputStream;
-
 import static android.os._Original_Build.VERSION_CODES.LOLLIPOP;
 
 /**
- * Base "bar" class for the window decor around the the edited layout.
+ * Base "bar" class for the window decor around the edited layout.
  * This is basically an horizontal layout that loads a given layout on creation (it is read
  * through {@link Class#getResourceAsStream(String)}).
  * <p>
@@ -88,9 +81,9 @@
                 layoutName);
     }
 
-    protected ImageView loadIcon(ImageView imageView, String iconName, Density density) {
+    protected ImageView loadIcon(ImageView imageView, String iconName, Density density, int color) {
         return SysUiResources.loadIcon(mContext, mSimulatedPlatformVersion, imageView, iconName,
-                density, false);
+                density, false, color);
     }
 
     protected ImageView loadIcon(int index, String iconName, Density density, boolean isRtl) {
@@ -98,39 +91,12 @@
         if (child instanceof ImageView) {
             ImageView imageView = (ImageView) child;
             return SysUiResources.loadIcon(mContext, mSimulatedPlatformVersion, imageView, iconName,
-                    density, isRtl);
+                    density, isRtl, Color.WHITE);
         }
 
         return null;
     }
 
-    protected ImageView loadIcon(ImageView imageView, String iconName, Density density,
-            boolean isRtl) {
-        LayoutDirection dir = isRtl ? LayoutDirection.RTL : null;
-        IconLoader iconLoader = new IconLoader(iconName, density, mSimulatedPlatformVersion, dir);
-        InputStream stream = iconLoader.getIcon();
-
-        if (stream != null) {
-            density = iconLoader.getDensity();
-            String path = iconLoader.getPath();
-            // look for a cached bitmap
-            Bitmap bitmap = Bridge.getCachedBitmap(path, Boolean.TRUE /*isFramework*/);
-            if (bitmap == null) {
-                Options options = new Options();
-                options.inDensity = density.getDpiValue();
-                bitmap = BitmapFactory.decodeStream(stream, null, options);
-                Bridge.setCachedBitmap(path, bitmap, Boolean.TRUE /*isFramework*/);
-            }
-
-            if (bitmap != null) {
-                BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);
-                imageView.setImageDrawable(drawable);
-            }
-        }
-
-        return imageView;
-    }
-
     protected TextView setText(int index, String string) {
         View child = getChildAt(index);
         if (child instanceof TextView) {
@@ -247,9 +213,7 @@
         resource = renderResources.resolveResValue(resource);
         if (resource != null) {
             ResourceType type = resource.getResourceType();
-            if (type == null || type == ResourceType.COLOR) {
-                // if no type is specified, the value may have been specified directly in the style
-                // file, rather than referencing a color resource value.
+            if (type == ResourceType.STYLE_ITEM || type == ResourceType.COLOR) {
                 try {
                     return ResourceHelper.getColor(resource.getValue());
                 } catch (NumberFormatException e) {
diff --git a/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index dc823f7..6842333 100644
--- a/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -17,11 +17,13 @@
 package com.android.layoutlib.bridge.bars;
 
 import com.android.ide.common.rendering.api.ILayoutLog;
+import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceNamespace;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.impl.ParserFactory;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
 import com.android.layoutlib.bridge.resources.IconLoader;
 import com.android.resources.Density;
 
@@ -42,9 +44,24 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.graphics.Color.WHITE;
+import static android.os._Original_Build.VERSION_CODES.M;
+import static com.android.layoutlib.bridge.bars.Config.getTimeColor;
+import static com.android.layoutlib.bridge.bars.Config.isGreaterOrEqual;
+
 public class StatusBar extends CustomBar {
 
     private final int mSimulatedPlatformVersion;
+    /**
+     * Color corresponding to light_mode_icon_color_single_tone
+     * from frameworks/base/packages/SettingsLib/res/values/colors.xml
+     */
+    private static final int LIGHT_ICON_COLOR = 0xffffffff;
+    /**
+     * Color corresponding to dark_mode_icon_color_single_tone
+     * from frameworks/base/packages/SettingsLib/res/values/colors.xml
+     */
+    private static final int DARK_ICON_COLOR = 0x99000000;
     /** Status bar background color attribute name. */
     private static final String ATTR_COLOR = "statusBarColor";
     /** Attribute for translucency property. */
@@ -57,7 +74,7 @@
     @SuppressWarnings("UnusedParameters")
     public StatusBar(Context context, AttributeSet attrs) {
         this((BridgeContext) context,
-                Density.getEnum(((BridgeContext) context).getMetrics().densityDpi),
+                Density.create(((BridgeContext) context).getMetrics().densityDpi),
                 ((BridgeContext) context).getConfiguration().getLayoutDirection() ==
                         View.LAYOUT_DIRECTION_RTL,
                 (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0,
@@ -95,20 +112,45 @@
             return;
         }
 
+        int foregroundColor = getForegroundColor(simulatedPlatformVersion);
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
         // We do know the order though.
         loadIcon(icons.get(0), "stat_sys_wifi_signal_4_fully."
-                        + Config.getWifiIconType(simulatedPlatformVersion), density);
-        loadIcon(icons.get(1), "stat_sys_battery_100.png", density);
+                        + Config.getWifiIconType(simulatedPlatformVersion), density,foregroundColor);
+        loadIcon(icons.get(1), "stat_sys_battery_100.png", density, foregroundColor);
         clockView.setText(Config.getTime(simulatedPlatformVersion));
-        clockView.setTextColor(Config.getTimeColor(simulatedPlatformVersion));
+        clockView.setTextColor(foregroundColor);
+    }
+
+    private int getForegroundColor(int platformVersion) {
+        if (isGreaterOrEqual(platformVersion, M)) {
+            RenderResources renderResources = getContext().getRenderResources();
+            boolean translucentBackground =
+                    ResourceHelper.getBooleanThemeFrameworkAttrValue(renderResources,
+                            ATTR_TRANSLUCENT, false);
+            if (translucentBackground) {
+                return WHITE;
+            }
+            boolean drawnByWindow =
+                    ResourceHelper.getBooleanThemeFrameworkAttrValue(renderResources,
+                            "windowDrawsSystemBarBackgrounds", false);
+            if (drawnByWindow) {
+                boolean lightStatusBar =
+                        ResourceHelper.getBooleanThemeFrameworkAttrValue(renderResources,
+                                "windowLightStatusBar", false);
+                return lightStatusBar ? DARK_ICON_COLOR : LIGHT_ICON_COLOR;
+            }
+            return WHITE;
+        } else {
+            return getTimeColor(platformVersion);
+        }
     }
 
     @Override
-    protected ImageView loadIcon(ImageView imageView, String iconName, Density density) {
+    protected ImageView loadIcon(ImageView imageView, String iconName, Density density, int color) {
         if (!iconName.endsWith(".xml")) {
-            return super.loadIcon(imageView, iconName, density);
+            return super.loadIcon(imageView, iconName, density, color);
         }
 
         // The xml is stored only in xhdpi.
@@ -123,8 +165,9 @@
                                 ParserFactory.create(stream, iconName),
                                 (BridgeContext) mContext,
                                 ResourceNamespace.ANDROID);
-                imageView.setImageDrawable(
-                        Drawable.createFromXml(mContext.getResources(), parser));
+                Drawable drawable = Drawable.createFromXml(mContext.getResources(), parser);
+                drawable.setTint(color);
+                imageView.setImageDrawable(drawable);
             } catch (XmlPullParserException e) {
                 Bridge.getLog().error(ILayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
                         null, null);
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index c8e5009..1ca3b9c 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -38,6 +38,8 @@
 import android.R.id;
 import android.annotation.NonNull;
 import android.graphics.Color;
+import android.graphics.Point;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
@@ -196,6 +198,25 @@
         mBuilder = null;
     }
 
+    @Override
+    public boolean getChildVisibleRect(View child, Rect r, Point offset, boolean forceParentCheck) {
+        return r.intersect(0, 0, getWidth(), getHeight());
+    }
+
+    @Override
+    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
+        int width = mRight - mLeft;
+        int height = mBottom - mTop;
+        if (width > 0 && height > 0) {
+            r.set(0, 0, width, height);
+            if (globalOffset != null) {
+                globalOffset.set(-mScrollX, -mScrollY);
+            }
+            return true;
+        }
+        return false;
+    }
+
     @NonNull
     private static View createSysUiOverlay(@NonNull BridgeContext context) {
         SysUiOverlay overlay =  new SysUiOverlay(context, 20, 10, 50, 40, 60);
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index c2430a8..98b5956 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -32,6 +32,7 @@
 import com.android.tools.layoutlib.annotations.Nullable;
 import com.android.tools.layoutlib.annotations.VisibleForTesting;
 
+import android.animation.AnimationHandler;
 import android.animation.PropertyValuesHolder_Accessor;
 import android.content.res.Configuration;
 import android.graphics.drawable.AdaptiveIconDrawable_Delegate;
@@ -42,6 +43,7 @@
 import android.view.Surface;
 import android.view.ViewConfiguration_Accessor;
 import android.view.WindowManagerGlobal_Delegate;
+import android.view.accessibility.AccessibilityInteractionClient_Accessor;
 import android.view.inputmethod.InputMethodManager_Accessor;
 
 import java.util.Collections;
@@ -51,6 +53,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantLock;
 
+import static android.os._Original_Build.VERSION.SDK_INT;
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED;
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
 import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
@@ -68,6 +71,12 @@
  *
  */
 public abstract class RenderAction<T extends RenderParams> {
+    /**
+     * Static field to store an SDK version coming from the render configuration.
+     * This is to be accessed when wanting to know the simulated SDK version instead
+     * of Build.VERSION.SDK_INT.
+     */
+    public static int sSimulatedSdk;
 
     private static final Set<String> COMPOSE_CLASS_FQNS =
             Set.of("androidx.compose.ui.tooling.ComposeViewAdapter",
@@ -99,6 +108,7 @@
      */
     protected RenderAction(T params) {
         mParams = params;
+        sSimulatedSdk = SDK_INT;
     }
 
     /**
@@ -276,6 +286,7 @@
         ILayoutLog currentLog = mParams.getLog();
         Bridge.setLog(currentLog);
         mContext.getRenderResources().setLogger(currentLog);
+        AnimationHandler.sAnimatorHandler = mContext.getAnimationHandlerThreadLocal();
     }
 
     /**
@@ -303,6 +314,7 @@
         ParserFactory.setParserFactory(null);
 
         PropertyValuesHolder_Accessor.clearClassCaches();
+        AccessibilityInteractionClient_Accessor.clearCaches();
     }
 
     public static BridgeContext getCurrentContext() {
@@ -467,6 +479,14 @@
         if (sCurrentContext != null) {
             // quit HandlerThread created during this session.
             HandlerThread_Delegate.cleanUp(sCurrentContext);
+
+            AnimationHandler animationHandler =
+                    sCurrentContext.getAnimationHandlerThreadLocal().get();
+            if (animationHandler != null) {
+                animationHandler.mDelayedCallbackStartTime.clear();
+                animationHandler.mAnimationCallbacks.clear();
+                animationHandler.mCommitCallbacks.clear();
+            }
         }
 
         sCurrentContext = null;
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
index 6a6e184..0dd35ce 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
@@ -39,6 +39,7 @@
 import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -78,7 +79,7 @@
             return Status.ERROR_NOT_A_DRAWABLE.createResult();
         }
 
-        Drawable d = ResourceHelper.getDrawable(drawableResource, context);
+        Drawable d = ResourceHelper.getDrawable(drawableResource, context, context.getTheme());
         if (d == null) {
             return Status.ERROR_NOT_A_DRAWABLE.createResult();
         }
@@ -128,15 +129,6 @@
             // Use screen size when either intrinsic width or height isn't available.
             w = screenWidth;
             h = screenHeight;
-        } else if (w > screenWidth || h > screenHeight) {
-            // If image wouldn't fit to the screen, resize it to avoid cropping.
-
-            // We need to find scale such that scale * w <= screenWidth, scale * h <= screenHeight.
-            double scale = Math.min((double) screenWidth / w, (double) screenHeight / h);
-
-            // scale * w / scale * h = w / h, so, proportions are preserved.
-            w = (int) Math.floor(scale * w);
-            h = (int) Math.floor(scale * h);
         }
 
         int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
@@ -149,47 +141,31 @@
         // Pre-draw setup.
         AttachInfo_Accessor.dispatchOnPreDraw(content);
 
-        // Draw into a new image.
-        BufferedImage image = getImage(w, h);
-
-        // Create an Android bitmap around the BufferedImage.
-        Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(),
-                Config.ARGB_8888);
-        bitmap.setPixels(image.getRGB(0, 0, image.getWidth(), image.getHeight(),
-                null, 0, image.getWidth()), 0, image.getWidth(), 0, 0, image
-                .getWidth(), image.getHeight());
-
-        // Create a Canvas around the Android bitmap.
+        Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
         Canvas canvas = new Canvas(bitmap);
         canvas.setDensity(hardwareConfig.getDensity().getDpiValue());
 
         // Draw.
         content.draw(canvas);
-        int[] pixels = new int[image.getWidth() * image.getHeight()];
-        bitmap.getPixels(pixels, 0, image.getWidth(), 0, 0, image.getWidth(),
+
+        if (w > screenWidth || h > screenHeight) {
+            // If image wouldn't fit to the screen, resize it to avoid cropping.
+
+            // We need to find scale such that scale * w <= screenWidth, scale * h <= screenHeight.
+            double scale = Math.min((double) screenWidth / w, (double) screenHeight / h);
+            bitmap = Bitmap.createScaledBitmap(bitmap, (int) (w * scale), (int) (h * scale), true);
+        }
+
+        // Copy bitmap into BufferedImage.
+        BufferedImage image = new BufferedImage(bitmap.getWidth(), bitmap.getHeight(),
+                BufferedImage.TYPE_INT_ARGB);
+        int[] imageData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+        bitmap.getPixels(imageData, 0, image.getWidth(), 0, 0, image.getWidth(),
                 image.getHeight());
-        image.setRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
 
         // Detach root from window after draw.
         AttachInfo_Accessor.detachFromWindow(content);
 
         return image;
     }
-
-    @NonNull
-    protected BufferedImage getImage(int w, int h) {
-        BufferedImage image = new BufferedImage(w > 0 ? w : 1,
-                h > 0 ? h : 1,
-                BufferedImage.TYPE_INT_ARGB);
-        Graphics2D gc = image.createGraphics();
-        gc.setComposite(AlphaComposite.Src);
-
-        gc.setColor(new Color(0x00000000, true));
-        gc.fillRect(0, 0, w, h);
-
-        // done
-        gc.dispose();
-
-        return image;
-    }
 }
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index ae5e401..9ed5d17 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -50,7 +50,6 @@
 import com.android.tools.idea.validator.hierarchy.CustomHierarchyHelper;
 import com.android.tools.layoutlib.annotations.NotNull;
 
-import android.animation.AnimationHandler;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -92,7 +91,10 @@
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
+import static android.os._Original_Build.VERSION.SDK_INT;
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
@@ -109,6 +111,10 @@
 public class RenderSessionImpl extends RenderAction<SessionParams> {
 
     private static final Canvas NOP_CANVAS = new NopCanvas();
+    private static final String SIMULATED_SDK_TOO_HIGH =
+            String.format("The current rendering only supports APIs up to %d. You may encounter " +
+                    "crashes if using with higher APIs. To avoid, you can set a lower API for " +
+                    "your previews.", SDK_INT);
 
     // scene state
     private RenderSession mScene;
@@ -198,7 +204,7 @@
     }
 
     /**
-     * Measures the the current layout if needed (see {@link #invalidateRenderingSize}).
+     * Measures the current layout if needed (see {@link #invalidateRenderingSize}).
      */
     private void measureLayout(@NonNull SessionParams params) {
         // only do the screen measure when needed.
@@ -310,6 +316,13 @@
             SessionParams params = getParams();
             BridgeContext context = getContext();
 
+            int simulatedVersion = params.getSimulatedPlatformVersion();
+            sSimulatedSdk = simulatedVersion > 0 ? simulatedVersion : SDK_INT;
+            if (sSimulatedSdk > SDK_INT) {
+                Bridge.getLog().fidelityWarning(ILayoutLog.TAG_UNSUPPORTED, SIMULATED_SDK_TOO_HIGH,
+                        null, null, null);
+            }
+
             if (Bridge.isLocaleRtl(params.getLocale())) {
                 if (!params.isRtlSupported()) {
                     Bridge.getLog().warning(ILayoutLog.TAG_RTL_NOT_ENABLED,
@@ -362,14 +375,8 @@
             mViewRoot.getViewRootImpl().mTmpFrames.displayFrame.set(mViewRoot.getLeft(),
                     mViewRoot.getTop(), mViewRoot.getRight(), mViewRoot.getBottom());
 
-            ViewRootImpl rootImpl = AttachInfo_Accessor.getRootView(mViewRoot);
-            if (rootImpl != null) {
-                ViewRootImpl_Accessor.setChild(rootImpl, mViewRoot);
-            }
-
             mSystemViewInfoList =
-                    visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(),
-                    false);
+                    visitAllChildren(mViewRoot, 0, 0, params, false);
 
             return SUCCESS.createResult();
         } catch (PostInflateException e) {
@@ -480,6 +487,13 @@
 
         SessionParams params = getParams();
 
+        int simulatedVersion = params.getSimulatedPlatformVersion();
+        sSimulatedSdk = simulatedVersion > 0 ? simulatedVersion : SDK_INT;
+        if (sSimulatedSdk > SDK_INT) {
+            Bridge.getLog().fidelityWarning(ILayoutLog.TAG_UNSUPPORTED, SIMULATED_SDK_TOO_HIGH,
+                    null, null, null);
+        }
+
         try {
             if (mViewRoot == null) {
                 return ERROR_NOT_INFLATED.createResult();
@@ -570,8 +584,12 @@
             }
 
             mSystemViewInfoList =
-                    visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(),
-                    false);
+                    visitAllChildren(mViewRoot, 0, 0, params, false);
+
+            Consumer<BufferedImage> imageTransformation = getParams().getImageTransformation();
+            if (imageTransformation != null) {
+                imageTransformation.accept(mImage);
+            }
 
             boolean enableLayoutValidation = Boolean.TRUE.equals(params.getFlag(RenderParamsFlags.FLAG_ENABLE_LAYOUT_VALIDATOR));
             boolean enableLayoutValidationImageCheck = Boolean.TRUE.equals(
@@ -853,15 +871,16 @@
      *
      * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
      */
-    private ViewInfo visit(View view, int hOffset, int vOffset, boolean setExtendedInfo,
+    private ViewInfo visit(View view, int hOffset, int vOffset, SessionParams params,
             boolean isContentFrame) {
-        ViewInfo result = createViewInfo(view, hOffset, vOffset, setExtendedInfo, isContentFrame);
+        ViewInfo result = createViewInfo(view, hOffset, vOffset, params.getExtendedViewInfoMode(),
+                isContentFrame);
 
         if (view instanceof ViewGroup) {
             ViewGroup group = ((ViewGroup) view);
             result.setChildren(visitAllChildren(group, isContentFrame ? 0 : hOffset,
                     isContentFrame ? 0 : vOffset,
-                    setExtendedInfo, isContentFrame));
+                    params, isContentFrame));
         }
         return result;
     }
@@ -880,7 +899,7 @@
      *                       part of the system decor.
      */
     private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int hOffset, int vOffset,
-            boolean setExtendedInfo, boolean isContentFrame) {
+            SessionParams params, boolean isContentFrame) {
         if (viewGroup == null) {
             return null;
         }
@@ -896,8 +915,7 @@
             List<ViewInfo> childrenWithOffset = new ArrayList<>(childCount);
             for (int i = 0; i < childCount; i++) {
                 ViewInfo[] childViewInfo =
-                        visitContentRoot(viewGroup.getChildAt(i), hOffset, vOffset,
-                        setExtendedInfo);
+                        visitContentRoot(viewGroup.getChildAt(i), hOffset, vOffset, params);
                 childrenWithoutOffset.add(childViewInfo[0]);
                 childrenWithOffset.add(childViewInfo[1]);
             }
@@ -906,7 +924,7 @@
         } else {
             List<ViewInfo> children = new ArrayList<>(childCount);
             for (int i = 0; i < childCount; i++) {
-                children.add(visit(viewGroup.getChildAt(i), hOffset, vOffset, setExtendedInfo,
+                children.add(visit(viewGroup.getChildAt(i), hOffset, vOffset, params,
                         isContentFrame));
             }
             return children;
@@ -920,26 +938,32 @@
      * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
      * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
      * offset is not needed.
+     * If a custom parser was passed inside the {@link SessionParams} argument, this will be used
+     * to generate the {@link ViewInfo}s. Otherwise, {@link RenderSessionImpl#visitAllChildren}
+     * will be used.
      *
      * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
      *         index 1 is with the offset.
      */
     @NonNull
-    private ViewInfo[] visitContentRoot(View view, int hOffset, int vOffset,
-            boolean setExtendedInfo) {
+    private ViewInfo[] visitContentRoot(View view, int hOffset, int vOffset, SessionParams params) {
         ViewInfo[] result = new ViewInfo[2];
         if (view == null) {
             return result;
         }
 
+        boolean setExtendedInfo = params.getExtendedViewInfoMode();
         result[0] = createViewInfo(view, 0, 0, setExtendedInfo, true);
         result[1] = createViewInfo(view, hOffset, vOffset, setExtendedInfo, true);
-        if (view instanceof ViewGroup) {
-            List<ViewInfo> children =
-                    visitAllChildren((ViewGroup) view, 0, 0, setExtendedInfo, true);
-            result[0].setChildren(children);
-            result[1].setChildren(children);
+        Function<Object, List<ViewInfo>> customParser = params.getCustomContentHierarchyParser();
+        List<ViewInfo> children = null;
+        if (customParser != null) {
+            children = customParser.apply(view);
+        } else if (view instanceof ViewGroup) {
+            children = visitAllChildren((ViewGroup) view, 0, 0, params, true);
         }
+        result[0].setChildren(children);
+        result[1].setChildren(children);
         return result;
     }
 
@@ -975,13 +999,13 @@
                     shiftY + view.getTop(),
                     shiftX + view.getRight(),
                     shiftY + view.getBottom(),
-                    view, view.getLayoutParams());
+                    view, null, view.getLayoutParams());
         } else {
             // We are part of the system decor.
             SystemViewInfo r = new SystemViewInfo(view.getClass().getName(),
                     getViewKey(view),
                     view.getLeft(), view.getTop(), view.getRight(),
-                    view.getBottom(), view, view.getLayoutParams());
+                    view.getBottom(), view, null, view.getLayoutParams());
             result = r;
             // We currently mark three kinds of views:
             // 1. Menus in the Action Bar
@@ -1184,6 +1208,19 @@
         }
     }
 
+    @Override
+    public void release() {
+        super.release();
+        if (mViewRoot == null) {
+            return;
+        }
+        ViewRootImpl viewRootImpl = mViewRoot.getViewRootImpl();
+        if (viewRootImpl == null) {
+            return;
+        }
+        ViewRootImpl_Accessor.detachFromWindow(viewRootImpl);
+    }
+
     private void disposeImageSurface() {
         if (mCanvas != null) {
             mCanvas.release();
@@ -1198,12 +1235,6 @@
             mImage = null;
             // detachFromWindow might create Handler callbacks, thus before Handler_Delegate.dispose
             AttachInfo_Accessor.detachFromWindow(mViewRoot);
-            AnimationHandler animationHandler = AnimationHandler.sAnimatorHandler.get();
-            if (animationHandler != null) {
-                animationHandler.mDelayedCallbackStartTime.clear();
-                animationHandler.mAnimationCallbacks.clear();
-                animationHandler.mCommitCallbacks.clear();
-            }
             getContext().getSessionInteractiveData().dispose();
             if (mViewInfoList != null) {
                 mViewInfoList.clear();
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 87bed3d..358795f 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -111,7 +111,7 @@
 public final class ResourceHelper {
     private static final Key<Set<ResourceValue>> KEY_GET_DRAWABLE =
             Key.create("ResourceHelper.getDrawable");
-    private static final Pattern sFloatPattern = Pattern.compile("(-?[0-9]*(?:\\.[0-9]+)?)(.*)");
+    private static final Pattern sFloatPattern = Pattern.compile("(-?[0-9]*(?:\\.[0-9]*)?)(.*)");
     private static final float[] sFloatOut = new float[1];
 
     private static final TypedValue mValue = new TypedValue();
@@ -368,7 +368,7 @@
         if (value instanceof DensityBasedResourceValue) {
             density = ((DensityBasedResourceValue) value).getResourceDensity();
             if (density == Density.NODPI || density == Density.ANYDPI) {
-                density = Density.getEnum(context.getConfiguration().densityDpi);
+                density = Density.create(context.getConfiguration().densityDpi);
             }
         }
 
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java b/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
index 9fea167..6f9092c 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
@@ -32,8 +32,9 @@
     }
 
     public SystemViewInfo(String name, Object cookie, int left, int top,
-            int right, int bottom, Object viewObject, Object layoutParamsObject) {
-        super(name, cookie, left, top, right, bottom, viewObject,
+            int right, int bottom, Object viewObject, Object accessibilityObject,
+            Object layoutParamsObject) {
+        super(name, cookie, left, top, right, bottom, viewObject, accessibilityObject,
                 layoutParamsObject);
     }
 
diff --git a/bridge/src/com/android/layoutlib/bridge/resources/SysUiResources.java b/bridge/src/com/android/layoutlib/bridge/resources/SysUiResources.java
index 84ed6a0..f8884d4 100644
--- a/bridge/src/com/android/layoutlib/bridge/resources/SysUiResources.java
+++ b/bridge/src/com/android/layoutlib/bridge/resources/SysUiResources.java
@@ -36,7 +36,6 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.widget.ImageView;
 
-import java.io.IOException;
 import java.io.InputStream;
 
 public class SysUiResources {
@@ -67,10 +66,8 @@
         return null;
     }
 
-    public static ImageView loadIcon(Context context, int api, ImageView imageView, String
-            iconName,
-            Density density, boolean
-            isRtl) {
+    public static ImageView loadIcon(Context context, int api, ImageView imageView,
+            String iconName, Density density, boolean isRtl, int color) {
         LayoutDirection dir = isRtl ? LayoutDirection.RTL : null;
         IconLoader iconLoader = new IconLoader(iconName, density, api,
                 dir);
@@ -90,6 +87,7 @@
 
             if (bitmap != null) {
                 BitmapDrawable drawable = new BitmapDrawable(context.getResources(), bitmap);
+                drawable.setTint(color);
                 imageView.setImageDrawable(drawable);
             }
         }
diff --git a/bridge/src/dalvik/system/VMRuntime_Delegate.java b/bridge/src/dalvik/system/VMRuntime_Delegate.java
index 2fe1015..23faf55 100644
--- a/bridge/src/dalvik/system/VMRuntime_Delegate.java
+++ b/bridge/src/dalvik/system/VMRuntime_Delegate.java
@@ -36,4 +36,9 @@
     /*package*/ static int getNotifyNativeInterval() {
         return VMRuntimeCommonHelper.getNotifyNativeInterval();
     }
+
+    @LayoutlibDelegate
+    public static boolean is64Bit(VMRuntime runtime) {
+        return true;
+    }
 }
diff --git a/bridge/tests/res/testApp/MyApplication/golden/activity.png b/bridge/tests/res/testApp/MyApplication/golden/activity.png
index a05349d..4546682 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/activity.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/activity.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon.png b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon.png
index 2d6938a..b438464 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_circle.png b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_circle.png
index 5570291..e939a57 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_circle.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_circle.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_green.png b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_green.png
index 61f1f18..b70c65d 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_green.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_green.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_orange.png b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_orange.png
index dd1dd57..31647c6 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_orange.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_dynamic_orange.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_rounded_corners.png b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_rounded_corners.png
index e0b6037..67deb6e 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_rounded_corners.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_rounded_corners.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_squircle.png b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_squircle.png
index 3e41ccc..6e63ef2 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_squircle.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon_squircle.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index 48a40cd..7ac28b6 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
index f8cec32..50b5f26 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png b/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
index c00823d..3887e29 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png b/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
index db0b343..9588148 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/asset.png b/bridge/tests/res/testApp/MyApplication/golden/asset.png
index b6193f6..f4467d6 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/asset.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/asset.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/auto-scale-image.png b/bridge/tests/res/testApp/MyApplication/golden/auto-scale-image.png
index 6a23995..7cabc39 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/auto-scale-image.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/auto-scale-image.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/bitmap_decoder.png b/bridge/tests/res/testApp/MyApplication/golden/bitmap_decoder.png
index 20f15a9..5be2d1a 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/bitmap_decoder.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/bitmap_decoder.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/context_theme_wrapper.png b/bridge/tests/res/testApp/MyApplication/golden/context_theme_wrapper.png
index 323d514..9e08e224 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/context_theme_wrapper.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/context_theme_wrapper.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/dark_status_bar.png b/bridge/tests/res/testApp/MyApplication/golden/dark_status_bar.png
new file mode 100644
index 0000000..34ff1ad
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/golden/dark_status_bar.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png b/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
index 5ed2706..7b1f1f1 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png b/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png
index 80e72b0..d6a4c5c 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/four_corners.png b/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
index 82e40ac..4e7feb4 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/light_status_bar.png b/bridge/tests/res/testApp/MyApplication/golden/light_status_bar.png
new file mode 100644
index 0000000..a37d8de
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/golden/light_status_bar.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/ninepatch_background.png b/bridge/tests/res/testApp/MyApplication/golden/ninepatch_background.png
index fefb3b7..6403637 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/ninepatch_background.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/ninepatch_background.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/ondraw_crash.png b/bridge/tests/res/testApp/MyApplication/golden/ondraw_crash.png
index d69667c..4051b05 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/ondraw_crash.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/ondraw_crash.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/onmeasure_crash.png b/bridge/tests/res/testApp/MyApplication/golden/onmeasure_crash.png
index 4d9f776..e27ae9e 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/onmeasure_crash.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/onmeasure_crash.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/rtl_ltr.png b/bridge/tests/res/testApp/MyApplication/golden/rtl_ltr.png
index 118e926..fab98dc 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/rtl_ltr.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/rtl_ltr.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/shadow_scrollview_test.png b/bridge/tests/res/testApp/MyApplication/golden/shadow_scrollview_test.png
index 19e65aa..55a9982 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/shadow_scrollview_test.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/shadow_scrollview_test.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/shadow_sizes_test.png b/bridge/tests/res/testApp/MyApplication/golden/shadow_sizes_test.png
index 84b7299..6093824 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/shadow_sizes_test.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/shadow_sizes_test.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/shadows_test_rounded_edge.png b/bridge/tests/res/testApp/MyApplication/golden/shadows_test_rounded_edge.png
index 7d9a51d..f1437af 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/shadows_test_rounded_edge.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/shadows_test_rounded_edge.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png b/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
index 2b2aab8..1300dd0 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png b/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
index 38924a3..7852c9e 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/software_layer.png b/bridge/tests/res/testApp/MyApplication/golden/software_layer.png
new file mode 100644
index 0000000..70465cf
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/golden/software_layer.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
index 5832c67..03da31e 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_gradient.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_gradient.png
index 769406e..67e502f 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_gradient.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_gradient.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_radial_gradient.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_radial_gradient.png
index 6882d79..4b1425a 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_radial_gradient.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_radial_gradient.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_in_image_view.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_in_image_view.png
index 759d535..055af89 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_in_image_view.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_in_image_view.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_itself.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_itself.png
index 4396a51..99e37ae 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_itself.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_with_tint_itself.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/SoftwareTextView.java b/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/SoftwareTextView.java
new file mode 100644
index 0000000..3d8cb0c
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/SoftwareTextView.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.test.myapplication.widgets;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+public class SoftwareTextView extends TextView {
+
+    public SoftwareTextView(Context context) {
+        super(context);
+        init();
+    }
+
+    public SoftwareTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public SoftwareTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public SoftwareTextView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    private void init() {
+        setLayerType(LAYER_TYPE_SOFTWARE, null);
+        setBackgroundColor(Color.RED);
+        setText("Software Layer");
+    }
+}
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml
index 7b338d1..d75aab1 100644
--- a/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml
@@ -16,4 +16,13 @@
         <item name="android:windowBackground">@drawable/theme_attribute_drawable</item>
     </style>
 
+    <style name="LightStatusBarTheme" parent="android:Theme.Material.Light.DarkActionBar">
+        <item name="android:statusBarColor">#ffff0000</item>
+        <item name="android:windowLightStatusBar">true</item>
+    </style>
+
+    <style name="DarkStatusBarTheme" parent="android:Theme.Material.Light.DarkActionBar">
+        <item name="android:statusBarColor">#ffff0000</item>
+    </style>
+
 </resources>
diff --git a/bridge/tests/run_tests.sh b/bridge/tests/run_tests.sh
index 91e88b6..bf33810 100755
--- a/bridge/tests/run_tests.sh
+++ b/bridge/tests/run_tests.sh
@@ -9,7 +9,7 @@
 readonly FAILURE_DIR=layoutlib-test-failures
 readonly FAILURE_ZIP=layoutlib-test-failures.zip
 
-readonly CLEAN_TMP_FILES=0
+readonly CLEAN_TMP_FILES=1
 readonly USE_SOONG=1
 
 readonly APP_NAME="regression"
@@ -76,6 +76,7 @@
 
 
 # Create zip of all failure screenshots
+rm -f ${OUT_DIR}/${FAILURE_ZIP}
 if [[ -d "${OUT_DIR}/${FAILURE_DIR}" ]]; then
     zip -q -j -r ${OUT_DIR}/${FAILURE_ZIP} ${OUT_DIR}/${FAILURE_DIR}
 fi
diff --git a/bridge/tests/src/android/content/res/BridgeTypedArrayTest.java b/bridge/tests/src/android/content/res/BridgeTypedArrayTest.java
index 3975927..dba0f76 100644
--- a/bridge/tests/src/android/content/res/BridgeTypedArrayTest.java
+++ b/bridge/tests/src/android/content/res/BridgeTypedArrayTest.java
@@ -52,6 +52,7 @@
         assertEquals(TYPE_STRING, BridgeTypedArray.getType("#notacolor"));
         assertEquals(TYPE_DIMENSION, BridgeTypedArray.getType("16dp"));
         assertEquals(TYPE_DIMENSION, BridgeTypedArray.getType(".16dp"));
+        assertEquals(TYPE_DIMENSION, BridgeTypedArray.getType("9999.dp"));
         assertEquals(TYPE_STRING, BridgeTypedArray.getType("16notaunit"));
         assertEquals(TYPE_INT_DEC, BridgeTypedArray.getType("98543"));
         assertEquals(TYPE_FLOAT, BridgeTypedArray.getType("43.364"));
diff --git a/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java b/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java
index f995d1a..a40dfed 100644
--- a/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java
+++ b/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java
@@ -20,8 +20,10 @@
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceNamespace;
 import com.android.ide.common.rendering.api.ResourceNamespace.Resolver;
+import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.tools.layoutlib.annotations.NotNull;
 
 import org.junit.Test;
 import org.xmlpull.v1.XmlPullParser;
@@ -34,12 +36,10 @@
 import static org.mockito.Mockito.when;
 
 public class BridgeXmlPullAttributesTest {
-
-    @Test
-    public void testGetAttributeIntValueForEnums() {
-        RenderResources renderResources = new RenderResources();
-
+    @NotNull
+    private static XmlPullParser prepareParser() {
         XmlPullParser parser = mock(XmlPullParser.class);
+
         when(parser.getAttributeValue(BridgeConstants.NS_RESOURCES, "layout_width"))
                 .thenReturn("match_parent");
         when(parser.getAttributeName(0)).thenReturn("layout_width");
@@ -50,34 +50,53 @@
         when(parser.getAttributeName(1)).thenReturn("my_custom_attr");
         when(parser.getAttributeNamespace(1)).thenReturn(BridgeConstants.NS_APP_RES_AUTO);
 
-        BridgeContext context = mock(BridgeContext.class);
-        when(context.getRenderResources()).thenReturn(renderResources);
+        return parser;
+    }
 
+    @NotNull
+    private static BridgeContext prepareContext() {
+        BridgeContext context = mock(BridgeContext.class);
+        RenderResources renderResources = new RenderResources() {
+            @Override
+            public ResourceValue resolveResValue(ResourceValue value) {
+                // Simulate behaviour from the actual resolver where a failed resolution will
+                // return the passed value.
+                return value;
+            }
+        };
+        when(context.getRenderResources()).thenReturn(renderResources);
         LayoutlibCallback callback = mock(LayoutlibCallback.class);
         when(callback.getImplicitNamespaces()).thenReturn(Resolver.EMPTY_RESOLVER);
         when(context.getLayoutlibCallback()).thenReturn(callback);
 
-        BridgeXmlPullAttributes attributes = new BridgeXmlPullAttributes(
-                parser,
-                context,
-                ResourceNamespace.RES_AUTO,
-                attrName -> {
-                    if ("layout_width".equals(attrName)) {
-                        return ImmutableMap.of(
-                                "match_parent", 123);
-                    }
-                    return ImmutableMap.of();
-                },
-                (ns, attrName) -> {
-                    if ("my_custom_attr".equals(attrName)) {
-                        return ImmutableMap.of(
-                                "a", 1,
-                                "b", 2
-                        );
-                    }
-                    return ImmutableMap.of();
-                });
+        return context;
+    }
 
+    private final XmlPullParser parser = prepareParser();
+    private final BridgeContext context = prepareContext();
+    private final  BridgeXmlPullAttributes attributes = new BridgeXmlPullAttributes(
+            parser,
+            context,
+            ResourceNamespace.RES_AUTO,
+            attrName -> {
+                if ("layout_width".equals(attrName)) {
+                    return ImmutableMap.of(
+                            "match_parent", 123);
+                }
+                return ImmutableMap.of();
+            },
+            (ns, attrName) -> {
+                if ("my_custom_attr".equals(attrName)) {
+                    return ImmutableMap.of(
+                            "a", 1,
+                            "b", 2
+                    );
+                }
+                return ImmutableMap.of();
+            });
+
+    @Test
+    public void testGetAttributeIntValueForEnums() {
         // Test a framework defined enum attribute
         assertEquals(123, attributes.getAttributeIntValue(BridgeConstants.NS_RESOURCES,
                 "layout_width", 500));
@@ -115,4 +134,11 @@
                 "my_other_attr", 500));
     }
 
+    @Test
+    public void testNotExistingAttributes() {
+        assertEquals(501, attributes.getAttributeUnsignedIntValue(BridgeConstants.NS_APP_RES_AUTO,
+                "my_other_attr", 501));
+        assertEquals(502, attributes.getAttributeResourceValue(BridgeConstants.NS_APP_RES_AUTO,
+                "my_other_attr", 502));
+    }
 }
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/android/AccessibilityTest.java b/bridge/tests/src/com/android/layoutlib/bridge/android/AccessibilityTest.java
index ed90d9b..e1cad4e 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/android/AccessibilityTest.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/android/AccessibilityTest.java
@@ -19,6 +19,8 @@
 import com.android.ide.common.rendering.api.RenderSession;
 import com.android.ide.common.rendering.api.Result;
 import com.android.ide.common.rendering.api.SessionParams;
+import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
+import com.android.ide.common.rendering.api.ViewInfo;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.intensive.LayoutLibTestCallback;
 import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
@@ -28,9 +30,13 @@
 import org.junit.Test;
 
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -58,6 +64,7 @@
         try {
             Result renderResult = session.render(50000);
             assertTrue(renderResult.isSuccess());
+            assertEquals(0, AccessibilityInteractionClient.sConnectionCache.size());
             View rootView = (View)session.getSystemRootViews().get(0).getViewObject();
             AccessibilityNodeInfo rootNode = rootView.createAccessibilityNodeInfo();
             assertNotNull(rootNode);
@@ -71,4 +78,101 @@
             session.dispose();
         }
     }
+
+    @Test
+    public void customHierarchyParserTest() throws FileNotFoundException,
+            ClassNotFoundException {
+        LayoutPullParser parser = createParserFromPath("allwidgets.xml");
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+        SessionParams params = getSessionParamsBuilder()
+                .setParser(parser)
+                .setConfigGenerator(ConfigGenerator.NEXUS_5)
+                .setCallback(layoutLibCallback)
+                .build();
+        params.setCustomContentHierarchyParser(viewObject -> {
+            List<ViewInfo> result = new ArrayList<>();
+            if (viewObject instanceof ViewGroup) {
+                ViewGroup view = (ViewGroup)viewObject;
+                for (int i = 0; i < view.getChildCount(); i++) {
+                    View child = view.getChildAt(i);
+                    ViewInfo childInfo =
+                            new ViewInfo(child.toString(), null, child.getLeft(), child.getTop(),
+                                    child.getRight(), child.getBottom(), child,
+                                    child.createAccessibilityNodeInfo(), null);
+                    childInfo.setChildren(null);
+                    result.add(childInfo);
+                }
+            }
+            return result;
+        });
+        RenderSession session = sBridge.createSession(params);
+        try {
+            Result renderResult = session.render(50000);
+            assertTrue(renderResult.isSuccess());
+            ViewInfo contentRootViewInfo = session.getRootViews().get(0);
+            contentRootViewInfo.getChildren().forEach(child -> {
+                assertNotNull(child.getAccessibilityObject());
+                assertEquals(0, child.getChildren().size());
+            });
+        } finally {
+            session.dispose();
+        }
+    }
+
+    @Test
+    public void testDialogAccessibility() throws Exception {
+        String layout =
+                "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+                        "              android:padding=\"16dp\"\n" +
+                        "              android:orientation=\"horizontal\"\n" +
+                        "              android:layout_width=\"fill_parent\"\n" +
+                        "              android:layout_height=\"fill_parent\">\n" +
+                        "    <com.android.layoutlib.test.myapplication.widgets.DialogView\n" +
+                        "             android:layout_height=\"wrap_content\"\n" +
+                        "             android:layout_width=\"wrap_content\" />\n" +
+                        "</LinearLayout>\n";
+        LayoutPullParser parser = LayoutPullParser.createFromString(layout);
+        // Create LayoutLibCallback.
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+        SessionParams params = getSessionParamsBuilder()
+                .setParser(parser)
+                .setCallback(layoutLibCallback)
+                .setTheme("Theme.Material.Light.NoActionBar.Fullscreen", false)
+                .setRenderingMode(RenderingMode.V_SCROLL)
+                .disableDecoration()
+                .build();
+        RenderSession session = sBridge.createSession(params);
+        session.setElapsedFrameTimeNanos(1);
+        try {
+            Result renderResult = session.render(50000);
+            assertTrue(renderResult.isSuccess());
+            assertEquals(0, AccessibilityInteractionClient.sConnectionCache.size());
+            View rootView =
+                    (View)((View) session.getSystemRootViews().get(1).getViewObject()).getParent();
+            int[] counter = {0};
+            session.execute(() -> {
+                AccessibilityNodeInfo rootNode = rootView.createAccessibilityNodeInfo();
+                assertNotNull(rootNode);
+                rootNode.setQueryFromAppProcessEnabled(rootView, true);
+                traverseAccessibilityTree(rootNode, counter);
+            });
+            assertEquals(0, AccessibilityInteractionClient.sConnectionCache.size());
+            assertEquals(17, counter[0]);
+        } finally {
+            session.dispose();
+        }
+    }
+
+    private void traverseAccessibilityTree(AccessibilityNodeInfo node, int[] counter) {
+        int childrenSize = node.getChildCount();
+        for (int i = 0; i < childrenSize; i++) {
+            AccessibilityNodeInfo child = node.getChild(i);
+            counter[0]++;
+            traverseAccessibilityTree(child, counter);
+        }
+    }
 }
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeContextTest.java b/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeContextTest.java
index b12adc9..83a4f80 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeContextTest.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeContextTest.java
@@ -21,6 +21,7 @@
 import com.android.layoutlib.bridge.impl.RenderAction;
 import com.android.layoutlib.bridge.impl.RenderActionTestUtil;
 import com.android.layoutlib.bridge.intensive.LayoutLibTestCallback;
+import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
 import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
 
 import org.junit.BeforeClass;
@@ -33,10 +34,13 @@
 import android.content.res.TypedArray;
 import android.os.PowerManager;
 import android.util.DisplayMetrics;
+import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
@@ -174,12 +178,12 @@
             ((DynamicRenderResources) context.getRenderResources()).setWallpaper(
                     "/com/android/layoutlib/testdata/wallpaper1.webp",
                     configuration.isNightModeActive());
-            assertEquals(-13226195, context.getResources().getColor(android.R.color.system_neutral1_800, null));
+            assertEquals(-13029845, context.getResources().getColor(android.R.color.system_neutral1_800, null));
 
             ((DynamicRenderResources) context.getRenderResources()).setWallpaper(
                     "/com/android/layoutlib/testdata/wallpaper2.webp",
                     configuration.isNightModeActive());
-            assertEquals(-13749969, context.getResources().getColor(android.R.color.system_neutral1_800, null));
+            assertEquals(-13946321, context.getResources().getColor(android.R.color.system_neutral1_800, null));
         } finally {
             context.disposeResources();
         }
@@ -204,4 +208,63 @@
         assertFalse(powerManager.isPowerSaveMode());
         assertTrue(powerManager.isInteractive());
     }
+
+    @Test
+    public void testTypedValue() throws Exception {
+        // Setup
+        // Create the layout pull parser for our resources (empty.xml can not be part of the test
+        // app as it won't compile).
+        LayoutPullParser parser = LayoutPullParser.createFromPath("/empty.xml");
+        // Create LayoutLibCallback.
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(RenderTestBase.getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+        SessionParams params = getSessionParamsBuilder()
+                .setConfigGenerator(ConfigGenerator.NEXUS_4)
+                .setParser(parser)
+                .setCallback(layoutLibCallback)
+                .build();
+        DisplayMetrics metrics = new DisplayMetrics();
+        Configuration configuration = RenderAction.getConfiguration(params);
+
+        BridgeContext mContext =
+                new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
+                        params.getAssets(), params.getLayoutlibCallback(), configuration,
+                        params.getTargetSdkVersion(), params.isRtlSupported());
+
+        TypedValue outValue = new TypedValue();
+        mContext.resolveThemeAttribute(android.R.attr.colorPrimary, outValue, true);
+        assertEquals(TypedValue.TYPE_INT_COLOR_ARGB8, outValue.type);
+        assertNotEquals(0, outValue.data);
+
+        outValue = new TypedValue();
+        mContext.resolveThemeAttribute(android.R.attr.colorError, outValue, true);
+        assertEquals(TypedValue.TYPE_INT_COLOR_RGB4, outValue.type);
+        assertEquals(-65536, outValue.data);
+
+        outValue = new TypedValue();
+        mContext.resolveThemeAttribute(attr.colorActivatedHighlight, outValue, true);
+        assertEquals(TypedValue.TYPE_INT_COLOR_ARGB4, outValue.type);
+        assertEquals(-872349952, outValue.data);
+
+        outValue = new TypedValue();
+        mContext.resolveThemeAttribute(android.R.attr.isLightTheme, outValue, true);
+        assertEquals(TypedValue.TYPE_INT_BOOLEAN, outValue.type);
+        assertEquals(1, outValue.data);
+
+        outValue = new TypedValue();
+        mContext.resolveThemeAttribute(android.R.attr.scrollbarFadeDuration, outValue, true);
+        assertEquals(TypedValue.TYPE_INT_DEC, outValue.type);
+        assertEquals(250, outValue.data);
+
+        outValue = new TypedValue();
+        mContext.resolveThemeAttribute(android.R.attr.scrollbarThumbHorizontal, outValue, true);
+        assertEquals(TypedValue.TYPE_STRING, outValue.type);
+        assertNotNull(outValue.string);
+
+        outValue = new TypedValue();
+        mContext.resolveThemeAttribute(android.R.attr.actionBarSize, outValue, true);
+        assertEquals(TypedValue.TYPE_DIMENSION, outValue.type);
+        assertEquals(14337, outValue.data);
+    }
 }
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/android/DynamicRenderResourcesTest.java b/bridge/tests/src/com/android/layoutlib/bridge/android/DynamicRenderResourcesTest.java
index 16a809b..ec7aa76 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/android/DynamicRenderResourcesTest.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/android/DynamicRenderResourcesTest.java
@@ -50,9 +50,9 @@
         assertEquals(-4478092, (int)dynamicColorMap.get("system_accent3_300"));
         assertEquals(-12963835, (int)dynamicColorMap.get("system_accent3_800"));
         assertEquals(-1, (int)dynamicColorMap.get("system_neutral1_0"));
-        assertEquals(-266518, (int)dynamicColorMap.get("system_neutral1_50"));
-        assertEquals(-4937306, (int)dynamicColorMap.get("system_neutral1_300"));
-        assertEquals(-13226195, (int)dynamicColorMap.get("system_neutral1_800"));
+        assertEquals(-4632, (int)dynamicColorMap.get("system_neutral1_50"));
+        assertEquals(-4675421, (int)dynamicColorMap.get("system_neutral1_300"));
+        assertEquals(-13029845, (int)dynamicColorMap.get("system_neutral1_800"));
         assertEquals(-1, (int)dynamicColorMap.get("system_neutral2_0"));
         assertEquals(-4632, (int)dynamicColorMap.get("system_neutral2_50"));
         assertEquals(-4413535, (int)dynamicColorMap.get("system_neutral2_300"));
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
index 7b9c163..c5ef0e0 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
@@ -46,7 +46,6 @@
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
 
-import android.R.attr;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.AssetManager;
@@ -57,7 +56,6 @@
 import android.graphics.Color;
 import android.util.DisplayMetrics;
 import android.util.StateSet;
-import android.util.TypedValue;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
@@ -72,10 +70,10 @@
 import java.lang.reflect.Field;
 import java.util.concurrent.TimeUnit;
 
+import static android.os._Original_Build.VERSION.SDK_INT;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -974,61 +972,6 @@
     }
 
     @Test
-    public void testTypedValue() throws Exception {
-        // Setup
-        // Create the layout pull parser for our resources (empty.xml can not be part of the test
-        // app as it won't compile).
-        LayoutPullParser parser = LayoutPullParser.createFromPath("/empty.xml");
-        // Create LayoutLibCallback.
-        LayoutLibTestCallback layoutLibCallback =
-                new LayoutLibTestCallback(RenderTestBase.getLogger(), mDefaultClassLoader);
-        layoutLibCallback.initResources();
-        SessionParams params = getSessionParamsBuilder()
-                .setConfigGenerator(ConfigGenerator.NEXUS_4)
-                .setParser(parser)
-                .setCallback(layoutLibCallback)
-                .build();
-        DisplayMetrics metrics = new DisplayMetrics();
-        Configuration configuration = RenderAction.getConfiguration(params);
-
-        BridgeContext mContext =
-                new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
-                        params.getAssets(), params.getLayoutlibCallback(), configuration,
-                        params.getTargetSdkVersion(), params.isRtlSupported());
-
-        TypedValue outValue = new TypedValue();
-        mContext.resolveThemeAttribute(android.R.attr.colorPrimary, outValue, true);
-        assertEquals(TypedValue.TYPE_INT_COLOR_ARGB8, outValue.type);
-        assertNotEquals(0, outValue.data);
-
-        outValue = new TypedValue();
-        mContext.resolveThemeAttribute(android.R.attr.colorError, outValue, true);
-        assertEquals(TypedValue.TYPE_INT_COLOR_RGB4, outValue.type);
-        assertEquals(-65536, outValue.data);
-
-        outValue = new TypedValue();
-        mContext.resolveThemeAttribute(attr.colorActivatedHighlight, outValue, true);
-        assertEquals(TypedValue.TYPE_INT_COLOR_ARGB4, outValue.type);
-        assertEquals(-872349952, outValue.data);
-
-        outValue = new TypedValue();
-        mContext.resolveThemeAttribute(android.R.attr.isLightTheme, outValue, true);
-        assertEquals(TypedValue.TYPE_INT_BOOLEAN, outValue.type);
-        assertEquals(1, outValue.data);
-
-        outValue = new TypedValue();
-        mContext.resolveThemeAttribute(android.R.attr.scrollbarFadeDuration, outValue, true);
-        assertEquals(TypedValue.TYPE_INT_DEC, outValue.type);
-        assertEquals(250, outValue.data);
-
-        outValue = new TypedValue();
-        mContext.resolveThemeAttribute(android.R.attr.scrollbarThumbHorizontal, outValue, true);
-        assertEquals(TypedValue.TYPE_STRING, outValue.type);
-        assertNotNull(outValue.string);
-        assertTrue(sRenderMessages.isEmpty());
-    }
-
-    @Test
     public void testColorStateList() throws Exception {
         final String STATE_LIST =
                 "<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n" +
@@ -2130,4 +2073,106 @@
 
         renderAndVerify(params, "html.png", TimeUnit.SECONDS.toNanos(2));
     }
+
+    @Test
+    public void testStatusBar() throws ClassNotFoundException {
+        final String layout =
+                "<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+                        "              android:layout_width=\"match_parent\"\n" +
+                        "              android:layout_height=\"match_parent\">\n" + "\n" +
+                        "    <TextView\n" +
+                        "        android:layout_width=\"wrap_content\"\n" +
+                        "        android:layout_height=\"wrap_content\"\n" +
+                        "        android:text=\"Test status bar colour\"\n" +
+                        "        android:textSize=\"30sp\"/>\n" +
+                        "</FrameLayout>";
+        // Create LayoutLibCallback.
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+
+        SessionParams params = getSessionParamsBuilder()
+                .setParser(LayoutPullParser.createFromString(layout))
+                .setCallback(layoutLibCallback)
+                .setTheme("DarkStatusBarTheme", true)
+                .setRenderingMode(RenderingMode.V_SCROLL)
+                .build();
+
+        renderAndVerify(params, "dark_status_bar.png", TimeUnit.SECONDS.toNanos(2));
+
+        params = getSessionParamsBuilder()
+                .setParser(LayoutPullParser.createFromString(layout))
+                .setCallback(layoutLibCallback)
+                .setTheme("LightStatusBarTheme", true)
+                .setRenderingMode(RenderingMode.V_SCROLL)
+                .build();
+
+        renderAndVerify(params, "light_status_bar.png", TimeUnit.SECONDS.toNanos(2));
+    }
+
+    @Test
+    public void testSoftwareLayer() throws Exception {
+        String layout =
+                "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+                        "              android:padding=\"16dp\"\n" +
+                        "              android:orientation=\"horizontal\"\n" +
+                        "              android:layout_width=\"fill_parent\"\n" +
+                        "              android:layout_height=\"fill_parent\">\n" +
+                        "    <com.android.layoutlib.test.myapplication.widgets.SoftwareTextView\n" +
+                        "             android:layout_height=\"200dp\"\n" +
+                        "             android:layout_width=\"wrap_content\" />\n" +
+                        "</LinearLayout>\n";
+        LayoutPullParser parser = LayoutPullParser.createFromString(layout);
+        // Create LayoutLibCallback.
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+
+        SessionParams params = getSessionParamsBuilder()
+                .setParser(parser)
+                .setCallback(layoutLibCallback)
+                .setTheme("Theme.Material.Light.NoActionBar.Fullscreen", false)
+                .setRenderingMode(RenderingMode.V_SCROLL)
+                .disableDecoration()
+                .build();
+
+        renderAndVerify(params, "software_layer.png",
+                TimeUnit.SECONDS.toNanos(2));
+    }
+
+    @Test
+    public void testHighSimulatedSdk() throws Exception {
+        String layout =
+                "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+                        "              android:padding=\"16dp\"\n" +
+                        "              android:orientation=\"horizontal\"\n" +
+                        "              android:layout_width=\"fill_parent\"\n" +
+                        "              android:layout_height=\"fill_parent\">\n" +
+                        "    <TextView\n" +
+                        "             android:layout_height=\"wrap_content\"\n" +
+                        "             android:layout_width=\"wrap_content\"\n" +
+                        "             android:text=\"This is a TextView\" />\n" +
+                        "</LinearLayout>\n";
+        LayoutPullParser parser = LayoutPullParser.createFromString(layout);
+        // Create LayoutLibCallback.
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+
+        SessionParams params = getSessionParamsBuilder()
+                .setParser(parser)
+                .setCallback(layoutLibCallback)
+                .setTheme("Theme.Material.Light.NoActionBar.Fullscreen", false)
+                .setRenderingMode(RenderingMode.V_SCROLL)
+                .setSimulatedSdk(SDK_INT + 1)
+                .disableDecoration()
+                .build();
+
+        render(sBridge, params, -1);
+        boolean hasApiError = sRenderMessages.removeIf(message -> message.equals(String.format(
+                "The current rendering only supports APIs up to %d. You may encounter crashes if " +
+                        "using with higher APIs. To avoid, you can set a lower API for your " +
+                        "previews.", SDK_INT)));
+        assertTrue(hasApiError);
+    }
 }
diff --git a/bridge/tests/src/com/android/tools/idea/validator/LayoutValidatorTests.java b/bridge/tests/src/com/android/tools/idea/validator/LayoutValidatorTests.java
index fd5e7f1..44b42ae 100644
--- a/bridge/tests/src/com/android/tools/idea/validator/LayoutValidatorTests.java
+++ b/bridge/tests/src/com/android/tools/idea/validator/LayoutValidatorTests.java
@@ -21,6 +21,7 @@
 import com.android.layoutlib.bridge.intensive.LayoutLibTestCallback;
 import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
 import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
+import com.android.layoutlib.common.util.ReflectionUtils;
 import com.android.tools.idea.validator.ValidatorData.CompoundFix;
 import com.android.tools.idea.validator.ValidatorData.Issue;
 import com.android.tools.idea.validator.ValidatorData.Level;
@@ -29,7 +30,9 @@
 
 import org.junit.Test;
 
+import android.util.SparseArray;
 import android.view.View;
+import android.view.accessibility.AccessibilityInteractionClient;
 
 import java.util.ArrayList;
 import java.util.EnumSet;
@@ -73,6 +76,9 @@
                 .build();
 
         renderAndVerify(params, "a11y_test1.png");
+        Object connectionCache = ReflectionUtils.getFieldValue(AccessibilityInteractionClient.class,
+                AccessibilityInteractionClient.getInstance(), "sConnectionCache");
+        assertEquals(0, ((SparseArray)connectionCache).size());
     }
 
     @Test
@@ -83,6 +89,8 @@
                     null,
                     SCALE_X_FOR_NEXUS_5,
                     SCALE_Y_FOR_NEXUS_5);
+            assertEquals(4, result.getSrcMap().size());
+            assertEquals(4, result.getNodeInfoMap().size());
             assertEquals(31, result.getIssues().size());
             ArrayList<Issue> errorIssues = new ArrayList<>();
             for (Issue issue : result.getIssues()) {
diff --git a/bridge/tests/src/com/android/tools/idea/validator/ValidatorResultTests.java b/bridge/tests/src/com/android/tools/idea/validator/ValidatorResultTests.java
index 618200c..b7e0e13 100644
--- a/bridge/tests/src/com/android/tools/idea/validator/ValidatorResultTests.java
+++ b/bridge/tests/src/com/android/tools/idea/validator/ValidatorResultTests.java
@@ -39,6 +39,7 @@
         assertNotNull(result);
         assertTrue(result.getIssues().isEmpty());
         assertTrue(result.getSrcMap().isEmpty());
+        assertTrue(result.getNodeInfoMap().isEmpty());
         assertNotNull(result.getMetric());
         assertEquals("Result containing 0 issues:\n", result.toString());
     }
diff --git a/common/src/com/android/tools/layoutlib/create/NativeConfig.java b/common/src/com/android/tools/layoutlib/create/NativeConfig.java
index 60a65ef..339ce78 100644
--- a/common/src/com/android/tools/layoutlib/create/NativeConfig.java
+++ b/common/src/com/android/tools/layoutlib/create/NativeConfig.java
@@ -109,6 +109,7 @@
             "android.provider.DeviceConfig#getLong",
             "android.provider.DeviceConfig#getProperty",
             "android.provider.DeviceConfig#getString",
+            "android.provider.Settings$Config#getContentResolver",
             "android.text.format.DateFormat#is24HourFormat",
             "android.util.Xml#newPullParser",
             "android.view.Choreographer#getFrameTimeNanos",
@@ -120,7 +121,6 @@
             "android.view.DisplayEventReceiver#nativeGetDisplayEventReceiverFinalizer",
             "android.view.DisplayEventReceiver#nativeInit",
             "android.view.HandlerActionQueue#postDelayed",
-            "android.view.LayoutInflater#initPrecompiledViews",
             "android.view.LayoutInflater#parseInclude",
             "android.view.LayoutInflater#rInflate",
             "android.view.MenuInflater#registerMenu",
@@ -137,6 +137,8 @@
             "android.view.View#measure",
             "android.view.ViewRootImpl#performHapticFeedback",
             "android.view.WindowManagerGlobal#getWindowManagerService",
+            "android.view.accessibility.AccessibilityManager#getInstance",
+            "android.view.accessibility.AccessibilityManager#getWindowTransformationSpec",
             "android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow",
             "android.view.inputmethod.InputMethodManager#isInEditMode",
             "android.view.inputmethod.InputMethodManager#showSoftInput",
@@ -146,6 +148,7 @@
             "com.android.internal.util.XmlUtils#convertValueToInt",
             "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
             "dalvik.system.VMRuntime#getNotifyNativeInterval",
+            "dalvik.system.VMRuntime#is64Bit",
             "dalvik.system.VMRuntime#newUnpaddedArray",
             "libcore.io.MemoryMappedFile#bigEndianIterator",
             "libcore.io.MemoryMappedFile#close",
diff --git a/create/Android.bp b/create/Android.bp
index 13a00a8..a8dcdaa 100644
--- a/create/Android.bp
+++ b/create/Android.bp
@@ -30,7 +30,7 @@
         "guava",
         "layoutlib-common",
         "layoutlib_create-classpath",
-        "atf-prebuilt-502584086",
+        "atf-prebuilt-557133692",
         "libprotobuf-java-lite",
     ],
 }
diff --git a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index 98055e3..55de0af 100644
--- a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -94,6 +94,8 @@
     private final Set<MethodReplacer> mMethodReplacers;
     private boolean mKeepAllNativeClasses;
 
+    /** A map { FQCN => set { field names } } which should have their final modifier removed */
+    private final Map<String, Set<String>> mRemoveFinalModifierFields;
 
     /**
      * Creates a new generator that can generate the output JAR with the stubbed classes.
@@ -218,6 +220,9 @@
 
         mRenameStaticInitializerClasses =
                 Arrays.stream(createInfo.getDeferredStaticInitializerClasses()).collect(Collectors.toSet());
+
+        mRemoveFinalModifierFields = new HashMap<>();
+        addToMap(createInfo.getRemovedFinalModifierFields(), mRemoveFinalModifierFields);
     }
 
     /**
@@ -427,6 +432,11 @@
             cv = new DeferStaticInitializerClassAdapter(cv);
         }
 
+        Set<String> removeFinalModifierFields = mRemoveFinalModifierFields.get(className);
+        if (removeFinalModifierFields != null && !removeFinalModifierFields.isEmpty()) {
+            cv = new RemoveFinalModifierFieldClassAdapter(cv, removeFinalModifierFields);
+        }
+
         // Make sure no class file has a version above 55 (corresponding to Java 11),
         // so that layoutlib can be run with JDK 11.
         cv = new ChangeFileVersionAdapter(mLog, 55, cv);
diff --git a/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index fb50c46..fbfd668 100644
--- a/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -129,6 +129,11 @@
         return DEFERRED_STATIC_INITIALIZER_CLASSES;
     }
 
+    @Override
+    public String[] getRemovedFinalModifierFields() {
+        return REMOVED_FINAL_MODIFIER_FIELDS;
+    }
+
     //-----
 
     private static final MethodReplacer[] METHOD_REPLACERS = new MethodReplacer[] {
@@ -331,6 +336,11 @@
         "android.view.Choreographer#mCallbackQueues", // required for tests only
         "android.view.Choreographer$CallbackQueue#mHead", // required for tests only
         "android.view.ViewRootImpl#mTmpFrames",
+        "android.view.accessibility.AccessibilityInteractionClient#sCaches",
+        "android.view.accessibility.AccessibilityInteractionClient#sClients",
+        "android.view.accessibility.AccessibilityInteractionClient#sConnectionCache",
+        "android.view.accessibility.AccessibilityInteractionClient#sDirectConnectionCount",
+        "android.view.accessibility.AccessibilityInteractionClient#sScrollingWindows",
         "com.android.internal.util.ArrayUtils#sCache",
     };
 
@@ -381,6 +391,12 @@
     private final static Map<String, InjectMethodRunnable> INJECTED_METHODS = Map.of(
             "android.content.Context", InjectMethodRunnables.CONTEXT_GET_FRAMEWORK_CLASS_LOADER);
 
+    /**
+     * List of fields for which we will remove the final modifier.
+     */
+    private final static String[] REMOVED_FINAL_MODIFIER_FIELDS =
+            new String[]{"android.animation.AnimationHandler#sAnimatorHandler"};
+
     public static class LinkedHashMapEldestReplacer implements MethodReplacer {
 
         private final String VOID_TO_MAP_ENTRY =
diff --git a/create/src/com/android/tools/layoutlib/create/DeferStaticInitializerClassAdapter.java b/create/src/com/android/tools/layoutlib/create/DeferStaticInitializerClassAdapter.java
index b5c331d..3ce901a 100644
--- a/create/src/com/android/tools/layoutlib/create/DeferStaticInitializerClassAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/DeferStaticInitializerClassAdapter.java
@@ -47,7 +47,7 @@
         // Java 9 does not allow static final field to be modified outside of <clinit>.
         // So if a field is static, it has to be non-final.
         if ((access & Opcodes.ACC_STATIC) != 0 ) {
-            access = access & ~Opcodes.ACC_FINAL;;
+            access = access & ~Opcodes.ACC_FINAL;
         }
         return super.visitField(access, name, desc, signature, value);
     }
diff --git a/create/src/com/android/tools/layoutlib/create/ICreateInfo.java b/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
index 83c5b24..e536bdc 100644
--- a/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
+++ b/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
@@ -129,6 +129,13 @@
 
     String[] getDeferredStaticInitializerClasses();
 
+    /**
+     * Returns a list of fields which should have their final modifier removed.
+     * The array values are in the form of the binary FQCN of the class containing the field and
+     * the field name separated by a '#'.
+     */
+    String[] getRemovedFinalModifierFields();
+
     interface MethodReplacer {
         boolean isNeeded(String owner, String name, String desc, String sourceClass);
 
diff --git a/create/src/com/android/tools/layoutlib/create/RemoveFinalModifierFieldClassAdapter.java b/create/src/com/android/tools/layoutlib/create/RemoveFinalModifierFieldClassAdapter.java
new file mode 100644
index 0000000..2f2d600
--- /dev/null
+++ b/create/src/com/android/tools/layoutlib/create/RemoveFinalModifierFieldClassAdapter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+
+import java.util.Set;
+
+import static org.objectweb.asm.Opcodes.ACC_FINAL;
+
+/**
+ * Removes the final modifier from the given fields.
+ */
+public class RemoveFinalModifierFieldClassAdapter extends ClassVisitor {
+
+    private final Set<String> mFieldNames;
+
+    public RemoveFinalModifierFieldClassAdapter(ClassVisitor cv, Set<String> fieldNames) {
+        super(Main.ASM_VERSION, cv);
+        mFieldNames = fieldNames;
+    }
+
+    @Override
+    public FieldVisitor visitField(int access, String name, String desc, String signature,
+            Object value) {
+        if (mFieldNames.contains(name)) {
+            access = access & ~ACC_FINAL;
+        }
+        return super.visitField(access, name, desc, signature, value);
+    }
+}
diff --git a/create/src/com/android/tools/layoutlib/create/StubExceptionMethodAdapter.java b/create/src/com/android/tools/layoutlib/create/StubExceptionMethodAdapter.java
index 73a57a2..322f065 100644
--- a/create/src/com/android/tools/layoutlib/create/StubExceptionMethodAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/StubExceptionMethodAdapter.java
@@ -24,7 +24,7 @@
 
 
 /**
- * {@link MethodVisitor} that replaces the method the implementation of the method with
+ * {@link MethodVisitor} that replaces the implementation of the method with
  * <code>
  * throw new RuntimeException("Stub!");
  * </code>
diff --git a/create/tests/src/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/create/tests/src/com/android/tools/layoutlib/create/AsmGeneratorTest.java
index aadab22..334bcd2 100644
--- a/create/tests/src/com/android/tools/layoutlib/create/AsmGeneratorTest.java
+++ b/create/tests/src/com/android/tools/layoutlib/create/AsmGeneratorTest.java
@@ -64,7 +64,7 @@
     private String mOsDestJar;
     private File mTempFile;
 
-    // ASM internal name for the the class in java package that should be refactored.
+    // ASM internal name for the class in java package that should be refactored.
     private static final String JAVA_CLASS_NAME = "notjava.lang.JavaClass";
 
     @Before
diff --git a/create/tests/src/com/android/tools/layoutlib/create/CreateInfoAdapter.java b/create/tests/src/com/android/tools/layoutlib/create/CreateInfoAdapter.java
index 3b1cb06..778a191 100644
--- a/create/tests/src/com/android/tools/layoutlib/create/CreateInfoAdapter.java
+++ b/create/tests/src/com/android/tools/layoutlib/create/CreateInfoAdapter.java
@@ -106,4 +106,9 @@
     public String[] getDeferredStaticInitializerClasses() {
         return EMPTY_STRING_ARRAY;
     }
+
+    @Override
+    public String[] getRemovedFinalModifierFields() {
+        return EMPTY_STRING_ARRAY;
+    }
 }
diff --git a/create/tests/src/com/android/tools/layoutlib/create/PromoteClassClassAdapterTest.java b/create/tests/src/com/android/tools/layoutlib/create/PromoteClassClassAdapterTest.java
index 3655ec2..0fa7ecb 100644
--- a/create/tests/src/com/android/tools/layoutlib/create/PromoteClassClassAdapterTest.java
+++ b/create/tests/src/com/android/tools/layoutlib/create/PromoteClassClassAdapterTest.java
@@ -155,7 +155,7 @@
         PromoteClassClassAdapter adapter = new PromoteClassClassAdapter(log, Set.of(
                 PackageProtectedClass.class.getName()));
         reader.accept(adapter, 0);
-        assertTrue(log.mLog.contains("[visit] - version=61, access=[public], " +
+        assertTrue(log.mLog.contains("[visit] - version=55, access=[public], " +
                 "name=com/android/tools/layoutlib/create/PackageProtectedClass, signature=null, " +
                 "superName=java/lang/Object, interfaces=[]"));
 
diff --git a/split_universal_binary.sh b/split_universal_binary.sh
index bd57245..55b5b38 100755
--- a/split_universal_binary.sh
+++ b/split_universal_binary.sh
@@ -26,6 +26,7 @@
 
 # Put the single architecture binaries inside the DIST folder to be accessible on ab/
 if [[ -d "${DIST_DIR}" ]]; then
+    mkdir -p ${DIST_DIR}/layoutlib_native/darwin
     cp -r ${OUT_DIR}/${ARM} ${DIST_DIR}/layoutlib_native/darwin
     cp -r ${OUT_DIR}/${X86} ${DIST_DIR}/layoutlib_native/darwin
 fi
diff --git a/validator/resources/strings.properties b/validator/resources/strings.properties
index 27f310c..3a07104 100644
--- a/validator/resources/strings.properties
+++ b/validator/resources/strings.properties
@@ -16,6 +16,7 @@
 #
 result_message_not_important_for_accessibility = This item was not found to be important for accessibility.
 result_message_no_content_desc = This item has no <tt>android:contentDescription</tt>.
+result_message_no_content_desc_generic = This item has no content description.
 result_message_not_visible = This item is not visible.
 result_message_not_enabled = This item isn\'t enabled.
 result_message_not_text_view = This item is not a <tt>TextView</tt>.
@@ -38,6 +39,7 @@
 long_clickable = long clickable
 clickable_and_long_clickable = clickable and long clickable
 actionable = actionable
+result_message_addendum_conflicting_elements_list = Conflicting element(s): <tt>%1$s</tt>.
 check_title_duplicate_speakable_text = Item descriptions
 result_message_brief_same_speakable_text = Multiple items have the same description.
 result_message_same_speakable_text = This %1$s item\'s speakable text: \"<tt>%2$s</tt>\" is identical to that of %3$d other item(s).
@@ -55,10 +57,14 @@
 check_title_redundant_description = Item type label
 result_message_english_locale_only = This check only runs on devices with locales set to English.
 result_message_brief_content_desc_contains_redundant_word = This item\'s <tt>android:contentDescription</tt> might contain unnecessary text.
+result_message_brief_content_desc_contains_redundant_word_generic = This item\'s content description might contain unnecessary text.
 result_message_content_desc_ends_with_view_type = This item\'s <tt>android:contentDescription</tt>, \"<tt>%1$s</tt>\" ends with the item\'s type.
 result_message_content_desc_contains_redundant_word = This item\'s <tt>android:contentDescription</tt>, \"<tt>%1$s</tt>\" contains the item type \"<tt>%2$s</tt>\".
+result_message_content_desc_contains_redundant_word_generic = This item\'s content description, \"<tt>%1$s</tt>\" contains the item type \"<tt>%2$s</tt>\".
 result_message_content_desc_contains_action = This item\'s <tt>android:contentDescription</tt>, \"<tt>%1$s</tt>\", contains the action \"<tt>%2$s</tt>\".
+result_message_content_desc_contains_action_generic = This item\'s content description, \"<tt>%1$s</tt>\", contains the action \"<tt>%2$s</tt>\".
 result_message_content_desc_contains_state = This item\'s <tt>android:contentDescription</tt>, \"<tt>%1$s</tt>\", contains the state \"<tt>%2$s</tt>\".
+result_message_content_desc_contains_state_generic = This item\'s content description, \"<tt>%1$s</tt>\", contains the state \"<tt>%2$s</tt>\".
 button_item_type = button
 checkbox_item_type = checkbox
 checkbox_item_type_separate_words = check box
@@ -73,6 +79,7 @@
 result_message_should_not_focus = This item would not be focused by a screen reader.
 result_message_web_content = Web content is not evaluated.
 result_message_unsupported_compose_content = Composable content is not evaluated in this environment.
+result_message_unsupported_flutter_content = Flutter content is not evaluated in this environment.
 result_message_missing_speakable_text = This item may not have a label readable by screen readers.
 check_title_text_contrast = Text contrast
 result_message_textview_empty = This <tt>TextView</tt> is empty.
@@ -158,12 +165,19 @@
 result_message_small_fixed_text_size = This text is small and may be difficult for some users to read. Consider using a larger size or specifying the text size in scaled pixels (<tt>sp</tt>).
 result_message_fixed_text_size = Consider specifying the text size in scaled pixels (<tt>sp</tt>).
 result_message_brief_fixed_width_text_view_with_scaled_text = This <tt>TextView</tt> has a fixed width and scalable text.
+result_message_brief_fixed_width_text_view_with_scaled_text_compose = This <tt>Text</tt> has a fixed width and scalable text.
 result_message_brief_fixed_height_text_view_with_scaled_text = This <tt>TextView</tt> has a fixed height and scalable text.
+result_message_brief_fixed_height_text_with_scaled_text_compose = This <tt>Text</tt> has a fixed height and scalable text.
 result_message_brief_fixed_size_text_view_with_scaled_text = This <tt>TextView</tt> has a fixed size and scalable text.
+result_message_brief_fixed_size_text_with_scaled_text_compose = This <tt>Text</tt> has a fixed size and scalable text.
 result_message_brief_fixed_width_view_group_with_scaled_text = This <tt>ViewGroup</tt> has a fixed width and contains a <tt>TextView</tt> with scalable text.
+result_message_brief_fixed_width_parent_with_scaled_text_compose = This element has a fixed width and contains a <tt>Text</tt> element with scalable text.
 result_message_brief_fixed_height_view_group_with_scaled_text = This <tt>ViewGroup</tt> has a fixed height and contains a <tt>TextView</tt> with scalable text.
+result_message_brief_fixed_height_parent_with_scaled_text_compose = This element has a fixed height and contains a <tt>Text</tt> element with scalable text.
 result_message_brief_fixed_size_view_group_with_scaled_text = This <tt>ViewGroup</tt> has a fixed size and contains a <tt>TextView</tt> with scalable text.
+result_message_brief_fixed_size_parent_with_scaled_text_compose = This element has a fixed size and contains a <tt>Text</tt> element with scalable text.
 result_message_fixed_size_text_view_with_scaled_text = Consider modifying the <tt>LayoutParams</tt> to allow for text expansion.
+result_message_fixed_size_text_with_scaled_text_compose = Consider modifying the size modifiers using <tt>sizeIn</tt> to allow for text expansion.
 check_title_unexposed_text = Unexposed Text
 result_message_unexposed_text = Ensure this item's accessibility label includes its visible text.
 result_message_text_detected_in_image_view = OCR results were detected inside this ImageView.
diff --git a/validator/src/com/android/tools/idea/validator/ValidatorResult.java b/validator/src/com/android/tools/idea/validator/ValidatorResult.java
index 7f25d46..9d708b5 100644
--- a/validator/src/com/android/tools/idea/validator/ValidatorResult.java
+++ b/validator/src/com/android/tools/idea/validator/ValidatorResult.java
@@ -21,6 +21,7 @@
 import com.android.tools.layoutlib.annotations.NotNull;
 
 import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -35,14 +36,21 @@
 public class ValidatorResult {
 
     @NotNull private final ImmutableBiMap<Long, View> mSrcMap;
+    @NotNull private final ImmutableBiMap<Long, AccessibilityNodeInfo> mNodeInfoMap;
     @NotNull private final ArrayList<Issue> mIssues;
     @NotNull private final Metric mMetric;
 
     /**
      * Please use {@link Builder} for creating results.
      */
-    private ValidatorResult(BiMap<Long, View> srcMap, ArrayList<Issue> issues, Metric metric) {
+    private ValidatorResult(BiMap<Long, View> srcMap,
+            BiMap<Long, AccessibilityNodeInfo> nodeInfoMap,
+            ArrayList<Issue> issues,
+            Metric metric) {
         mSrcMap = ImmutableBiMap.<Long, View>builder().putAll(srcMap).build();
+        mNodeInfoMap = ImmutableBiMap.<Long, AccessibilityNodeInfo>builder()
+                .putAll(nodeInfoMap)
+                .build();
         mIssues = issues;
         mMetric = metric;
     }
@@ -55,6 +63,13 @@
     }
 
     /**
+     * @return the map from source ID to AccessibilityNodeInfo.
+     */
+    public ImmutableBiMap<Long, AccessibilityNodeInfo> getNodeInfoMap() {
+        return mNodeInfoMap;
+    }
+
+    /**
      * @return list of issues.
      */
     public List<Issue> getIssues() {
@@ -89,11 +104,12 @@
 
     public static class Builder {
         @NotNull public final BiMap<Long, View> mSrcMap = HashBiMap.create();
+        @NotNull public final BiMap<Long, AccessibilityNodeInfo> mNodeInfoMap = HashBiMap.create();
         @NotNull public final ArrayList<Issue> mIssues = new ArrayList<>();
         @NotNull public final Metric mMetric = new Metric();
 
         public ValidatorResult build() {
-            return new ValidatorResult(mSrcMap, mIssues, mMetric);
+            return new ValidatorResult(mSrcMap, mNodeInfoMap, mIssues, mMetric);
         }
     }
 
diff --git a/validator/src/com/android/tools/idea/validator/ValidatorUtil.java b/validator/src/com/android/tools/idea/validator/ValidatorUtil.java
index 6078046..fa2862d 100644
--- a/validator/src/com/android/tools/idea/validator/ValidatorUtil.java
+++ b/validator/src/com/android/tools/idea/validator/ValidatorUtil.java
@@ -83,8 +83,6 @@
          * uses be redirected.
          */
         StringManager.setResourceBundleProvider(locale -> ResourceBundle.getBundle("strings"));
-        // Enable using AccessibilityNodeInfo in addition to View for accessibility testing
-        AccessibilityHierarchyAndroid.viewOverlayEnabled = true;
     }
 
     // Visible for testing.
@@ -130,7 +128,9 @@
         try {
             hierarchy.mView = AccessibilityHierarchyAndroid
                     .newBuilder(view)
+                    .enableViewOverlay()
                     .setViewOriginMap(builder.mSrcMap)
+                    .setNodeInfoOriginMap(builder.mNodeInfoMap)
                     .setObtainCharacterLocations(LayoutValidator.obtainCharacterLocations())
                     .setCharacterLocationArgMaxLength(CHARACTER_LOCATION_ARG_MAX_LENGTH)
                     .setCustomViewBuilder(new CustomViewBuilderAndroid() {
diff --git a/validator/src/com/android/tools/idea/validator/hierarchy/CustomHierarchyHelper.java b/validator/src/com/android/tools/idea/validator/hierarchy/CustomHierarchyHelper.java
index eee2f32..5c8b2e9 100644
--- a/validator/src/com/android/tools/idea/validator/hierarchy/CustomHierarchyHelper.java
+++ b/validator/src/com/android/tools/idea/validator/hierarchy/CustomHierarchyHelper.java
@@ -48,13 +48,29 @@
             // This is required as layoutlib does not know the support library such as
             // MaterialButton. LayoutlibCallback calls for studio which understands all the maven
             // pulled library.
-            Class button = callback.findClass(
+            Class<?> button = callback.findClass(
                     "com.google.android.material.button.MaterialButton");
             if (button.isInstance(fromView)) {
                 Method isCheckable = button.getMethod("isCheckable");
                 Object toReturn = isCheckable.invoke(fromView);
                 return (toReturn instanceof Boolean) && ((Boolean) toReturn);
             }
+
+            Class<?> card = callback.findClass(
+                    "com.google.android.material.card.MaterialCardView");
+            if (card.isInstance(fromView)) {
+                Method isCheckable = card.getMethod("isCheckable");
+                Object toReturn = isCheckable.invoke(fromView);
+                return (toReturn instanceof Boolean) && ((Boolean) toReturn);
+            }
+
+            Class<?> chip = callback.findClass(
+                    "com.google.android.material.chip.Chip");
+            if (chip.isInstance(fromView)) {
+                Method isCheckable = chip.getMethod("isCheckable");
+                Object toReturn = isCheckable.invoke(fromView);
+                return (toReturn instanceof Boolean) && ((Boolean) toReturn);
+            }
         } catch (ClassNotFoundException |
                  NoSuchMethodException |
                  IllegalAccessException |