aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-01 00:17:23 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-01 00:17:23 +0000
commit3b42f824de3a7d01d02f635fd17fcd400cb32f01 (patch)
tree5e67a9cd2b723f1346e2300012f6ad208bf814c6
parentf4b2f6950e0784b4a34e70fb0b13318a65d796f0 (diff)
parentb2ba3bf14ca96ec852d581c511412cca3920b6f2 (diff)
downloadlayoutlib-3b42f824de3a7d01d02f635fd17fcd400cb32f01.tar.gz
Snap for 11162593 from b2ba3bf14ca96ec852d581c511412cca3920b6f2 to 24Q1-release
Change-Id: Ia1b0ef3284278fc7f8a2f152b7283405605220af
-rw-r--r--bridge/src/android/view/AttachInfo_Accessor.java2
-rw-r--r--bridge/src/android/view/ViewRootImpl_Accessor.java10
-rw-r--r--bridge/src/android/view/WindowManagerImpl.java18
-rw-r--r--bridge/src/android/view/accessibility/AccessibilityInteractionClient_Accessor.java27
-rw-r--r--bridge/src/com/android/layoutlib/bridge/impl/Layout.java21
-rw-r--r--bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java2
-rw-r--r--bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java18
-rw-r--r--bridge/tests/src/com/android/layoutlib/bridge/android/AccessibilityTest.java58
-rw-r--r--create/src/com/android/tools/layoutlib/create/CreateInfo.java5
9 files changed, 153 insertions, 8 deletions
diff --git a/bridge/src/android/view/AttachInfo_Accessor.java b/bridge/src/android/view/AttachInfo_Accessor.java
index 2e38b31793..b8c8f0e060 100644
--- a/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/bridge/src/android/view/AttachInfo_Accessor.java
@@ -37,6 +37,8 @@ public class AttachInfo_Accessor {
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);
}
diff --git a/bridge/src/android/view/ViewRootImpl_Accessor.java b/bridge/src/android/view/ViewRootImpl_Accessor.java
index 691f59ae46..d15952ad3d 100644
--- a/bridge/src/android/view/ViewRootImpl_Accessor.java
+++ b/bridge/src/android/view/ViewRootImpl_Accessor.java
@@ -26,9 +26,13 @@ public class ViewRootImpl_Accessor {
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) {
diff --git a/bridge/src/android/view/WindowManagerImpl.java b/bridge/src/android/view/WindowManagerImpl.java
index eb1e22c736..285ca9e5e4 100644
--- a/bridge/src/android/view/WindowManagerImpl.java
+++ b/bridge/src/android/view/WindowManagerImpl.java
@@ -41,6 +41,8 @@ import com.android.internal.R;
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 @@ public class WindowManagerImpl implements WindowManager {
}
}
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 @@ public class WindowManagerImpl implements WindowManager {
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 0000000000..8c87c22e88
--- /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/com/android/layoutlib/bridge/impl/Layout.java b/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index c8e5009888..1ca3b9c2cc 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 com.android.resources.ScreenOrientation;
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 @@ class Layout extends FrameLayout {
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 8048ff1e1a..98b59565f7 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -43,6 +43,7 @@ import android.view.IWindowManagerImpl;
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;
@@ -313,6 +314,7 @@ public abstract class RenderAction<T extends RenderParams> {
ParserFactory.setParserFactory(null);
PropertyValuesHolder_Accessor.clearClassCaches();
+ AccessibilityInteractionClient_Accessor.clearCaches();
}
public static BridgeContext getCurrentContext() {
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index de7f651bab..9ed5d17531 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -375,11 +375,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
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, false);
@@ -1213,6 +1208,19 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
+ @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();
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 149680868e..e1cad4ee2d 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,7 @@ package com.android.layoutlib.bridge.android;
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;
@@ -30,6 +31,7 @@ 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;
@@ -62,6 +64,7 @@ public class AccessibilityTest extends RenderTestBase {
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);
@@ -117,4 +120,59 @@ public class AccessibilityTest extends RenderTestBase {
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/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index b2b7e7084b..fbfd66895f 100644
--- a/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -336,6 +336,11 @@ public final class CreateInfo implements ICreateInfo {
"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",
};