From 0d73e1abeb557deafa9cc26b3a41673287ee55fa Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Wed, 7 Jun 2023 17:13:37 +0000 Subject: Pass LayoutParams from SCVH to Parent window There are some params that a view or window can set that needs to be handled by WMS. However, SCVH have no interface into WMS since they are handled in the client process. Instead, pass the params to their host parent and let the host ensure the correct params are handled in WMS. Test: SurfaceControlViewHostTests Bug: 281687307 This reverts commit 41dd323ac08077f22b9e305d9be9848a19c564d9. Reason for revert: Disable failing test. b/286245842 Change-Id: If0e61bfc4d1e32513316d4a9a22faf2ec77e690c --- .../java/android/view/ISurfaceControlViewHost.aidl | 6 +++ .../view/ISurfaceControlViewHostParent.aidl | 27 ++++++++++ core/java/android/view/SurfaceControlViewHost.java | 15 ++++-- core/java/android/view/SurfaceView.java | 60 ++++++++++++++++++++-- .../java/android/view/WindowlessWindowManager.java | 48 ++++++++++++++++- .../AdminSecondaryLockScreenControllerTest.java | 2 + 6 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 core/java/android/view/ISurfaceControlViewHostParent.aidl diff --git a/core/java/android/view/ISurfaceControlViewHost.aidl b/core/java/android/view/ISurfaceControlViewHost.aidl index 15008ae18618..fd4b329570d9 100644 --- a/core/java/android/view/ISurfaceControlViewHost.aidl +++ b/core/java/android/view/ISurfaceControlViewHost.aidl @@ -19,6 +19,7 @@ package android.view; import android.content.res.Configuration; import android.graphics.Rect; import android.view.InsetsState; +import android.view.ISurfaceControlViewHostParent; import android.window.ISurfaceSyncGroup; /** @@ -34,4 +35,9 @@ interface ISurfaceControlViewHost { oneway void onDispatchDetachedFromWindow(); oneway void onInsetsChanged(in InsetsState state, in Rect insetFrame); ISurfaceSyncGroup getSurfaceSyncGroup(); + /** + * Attaches the parent interface so the embedded content can communicate back to the parent. + * If null is passed in, it will remove the parent interface and no more updates will be sent. + */ + oneway void attachParentInterface(in @nullable ISurfaceControlViewHostParent parentInterface); } diff --git a/core/java/android/view/ISurfaceControlViewHostParent.aidl b/core/java/android/view/ISurfaceControlViewHostParent.aidl new file mode 100644 index 000000000000..f42e00148587 --- /dev/null +++ b/core/java/android/view/ISurfaceControlViewHostParent.aidl @@ -0,0 +1,27 @@ +/* +** Copyright 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; + +import android.view.WindowManager; + +/** + * API from embedded content in SurfaceControlViewHost to parent containing the embedded. + * {@hide} + */ +oneway interface ISurfaceControlViewHostParent { + void updateParams(in WindowManager.LayoutParams[] childAttrs); +} diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java index c8cf7d9a5194..effc127dabd2 100644 --- a/core/java/android/view/SurfaceControlViewHost.java +++ b/core/java/android/view/SurfaceControlViewHost.java @@ -54,7 +54,7 @@ public class SurfaceControlViewHost { private final static String TAG = "SurfaceControlViewHost"; private final ViewRootImpl mViewRoot; private final CloseGuard mCloseGuard = CloseGuard.get(); - private WindowlessWindowManager mWm; + private final WindowlessWindowManager mWm; private SurfaceControl mSurfaceControl; private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection; @@ -67,9 +67,7 @@ public class SurfaceControlViewHost { return; } mViewRoot.mHandler.post(() -> { - if (mWm != null) { - mWm.setConfiguration(configuration); - } + mWm.setConfiguration(configuration); if (mViewRoot != null) { mViewRoot.forceWmRelayout(); } @@ -116,6 +114,11 @@ public class SurfaceControlViewHost { } return null; } + + @Override + public void attachParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) { + mViewRoot.mHandler.post(() -> mWm.setParentInterface(parentInterface)); + } } private ISurfaceControlViewHost mRemoteInterface = new ISurfaceControlViewHostImpl(); @@ -148,10 +151,11 @@ public class SurfaceControlViewHost { private SurfaceControl mSurfaceControl; private final IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection; private final IBinder mInputToken; + @NonNull private final ISurfaceControlViewHost mRemoteInterface; SurfacePackage(SurfaceControl sc, IAccessibilityEmbeddedConnection connection, - IBinder inputToken, ISurfaceControlViewHost ri) { + IBinder inputToken, @NonNull ISurfaceControlViewHost ri) { mSurfaceControl = sc; mAccessibilityEmbeddedConnection = connection; mInputToken = inputToken; @@ -213,6 +217,7 @@ public class SurfaceControlViewHost { /** * @hide */ + @NonNull public ISurfaceControlViewHost getRemoteInterface() { return mRemoteInterface; } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 0e4cf89e7772..1e268bed3b17 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_OVERLAY_SUBLAYER; import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER; import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER; @@ -40,6 +41,7 @@ import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.RemoteException; import android.os.SystemClock; import android.util.ArraySet; import android.util.AttributeSet; @@ -54,6 +56,8 @@ import com.android.internal.view.SurfaceCallbackHelper; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; @@ -302,6 +306,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private SurfaceControl mBlastSurfaceControl; private BLASTBufferQueue mBlastBufferQueue; + private final ConcurrentLinkedQueue mEmbeddedWindowParams = + new ConcurrentLinkedQueue<>(); + + private final ISurfaceControlViewHostParent mSurfaceControlViewHostParent = + new ISurfaceControlViewHostParent.Stub() { + @Override + public void updateParams(WindowManager.LayoutParams[] childAttrs) { + mEmbeddedWindowParams.clear(); + mEmbeddedWindowParams.addAll(Arrays.asList(childAttrs)); + + if (isAttachedToWindow()) { + runOnUiThread(() -> { + if (mParent != null) { + mParent.recomputeViewAttributes(SurfaceView.this); + } + }); + } + } + }; + public SurfaceView(Context context) { this(context, null); } @@ -801,9 +825,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall mBlastSurfaceControl = null; } - if (releaseSurfacePackage && mSurfacePackage != null) { - mSurfacePackage.release(); - mSurfacePackage = null; + if (mSurfacePackage != null) { + try { + mSurfacePackage.getRemoteInterface().attachParentInterface(null); + mEmbeddedWindowParams.clear(); + } catch (RemoteException e) { + Log.d(TAG, "Failed to remove parent interface from SCVH. Likely SCVH is " + + "already dead"); + } + if (releaseSurfacePackage) { + mSurfacePackage.release(); + mSurfacePackage = null; + } } applyTransactionOnVriDraw(transaction); @@ -1854,6 +1887,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall applyTransactionOnVriDraw(transaction); } mSurfacePackage = p; + try { + mSurfacePackage.getRemoteInterface().attachParentInterface( + mSurfaceControlViewHostParent); + } catch (RemoteException e) { + Log.d(TAG, "Failed to attach parent interface to SCVH. Likely SCVH is already dead."); + } if (isFocused()) { requestEmbeddedFocus(true); @@ -2014,4 +2053,19 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall mBlastBufferQueue.mergeWithNextTransaction(transaction, frameNumber); } } + + @Override + void performCollectViewAttributes(AttachInfo attachInfo, int visibility) { + super.performCollectViewAttributes(attachInfo, visibility); + if (mEmbeddedWindowParams.isEmpty()) { + return; + } + + for (WindowManager.LayoutParams embeddedWindowAttr : mEmbeddedWindowParams) { + if ((embeddedWindowAttr.flags & FLAG_KEEP_SCREEN_ON) == FLAG_KEEP_SCREEN_ON) { + attachInfo.mKeepScreenOn = true; + break; + } + } + } } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 96bfb2d9e1e6..7d3d283a45f2 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -49,7 +49,8 @@ public class WindowlessWindowManager implements IWindowSession { private class State { SurfaceControl mSurfaceControl; - WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); + final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); + final WindowManager.LayoutParams mLastReportedParams = new WindowManager.LayoutParams(); int mDisplayId; IBinder mInputChannelToken; Region mInputRegion; @@ -94,6 +95,8 @@ public class WindowlessWindowManager implements IWindowSession { private final MergedConfiguration mTmpConfig = new MergedConfiguration(); private final WindowlessWindowLayout mLayout = new WindowlessWindowLayout(); + private ISurfaceControlViewHostParent mParentInterface; + public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface, IBinder hostInputToken) { mRootSurface = rootSurface; @@ -244,6 +247,7 @@ public class WindowlessWindowManager implements IWindowSession { final int res = WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE | WindowManagerGlobal.ADD_FLAG_USE_BLAST; + sendLayoutParamsToParent(); // Include whether the window is in touch mode. return isInTouchModeInternal(displayId) ? res | WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE : res; @@ -425,6 +429,7 @@ public class WindowlessWindowManager implements IWindowSession { outInsetsState.set(mInsetsState); } + sendLayoutParamsToParent(); return 0; } @@ -645,4 +650,45 @@ public class WindowlessWindowManager implements IWindowSession { " we shouldn't get here!"); return false; } + + void setParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) { + IBinder oldInterface = mParentInterface == null ? null : mParentInterface.asBinder(); + IBinder newInterface = parentInterface == null ? null : parentInterface.asBinder(); + // If the parent interface has changed, it needs to clear the last reported params so it + // will update the new interface with the params. + if (oldInterface != newInterface) { + clearLastReportedParams(); + } + mParentInterface = parentInterface; + sendLayoutParamsToParent(); + } + + private void clearLastReportedParams() { + WindowManager.LayoutParams emptyParam = new WindowManager.LayoutParams(); + for (State windowInfo : mStateForWindow.values()) { + windowInfo.mLastReportedParams.copyFrom(emptyParam); + } + } + + private void sendLayoutParamsToParent() { + if (mParentInterface == null) { + return; + } + WindowManager.LayoutParams[] params = + new WindowManager.LayoutParams[mStateForWindow.size()]; + int index = 0; + boolean hasChanges = false; + for (State windowInfo : mStateForWindow.values()) { + int changes = windowInfo.mLastReportedParams.copyFrom(windowInfo.mParams); + hasChanges |= (changes != 0); + params[index++] = windowInfo.mParams; + } + + if (hasChanges) { + try { + mParentInterface.updateParams(params); + } catch (RemoteException e) { + } + } + } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java index f5cd0ca7ab3b..319a02d911ed 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java @@ -50,6 +50,7 @@ import com.android.systemui.SysuiTestCase; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -59,6 +60,7 @@ import org.mockito.MockitoAnnotations; @RunWithLooper @RunWith(AndroidTestingRunner.class) @SmallTest +@Ignore("b/286245842") public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase { private static final int TARGET_USER_ID = KeyguardUpdateMonitor.getCurrentUser(); -- cgit v1.2.3-59-g8ed1b