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 Change-Id: I7cc91ac6d4a7b96446b0b923d1f229f4353db216
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
27
core/java/android/view/ISurfaceControlViewHostParent.aidl
Normal file
27
core/java/android/view/ISurfaceControlViewHostParent.aidl
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user