diff options
6 files changed, 149 insertions, 9 deletions
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<WindowManager.LayoutParams> 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(); |