Merge "Use correct focus token for SCVH#getFocusGrantToken" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b2be29bc43
@@ -400,8 +400,7 @@ public class SurfaceControlViewHost {
|
||||
public @Nullable SurfacePackage getSurfacePackage() {
|
||||
if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) {
|
||||
return new SurfacePackage(new SurfaceControl(mSurfaceControl, "getSurfacePackage"),
|
||||
mAccessibilityEmbeddedConnection,
|
||||
mWm.getFocusGrantToken(), mRemoteInterface);
|
||||
mAccessibilityEmbeddedConnection, getFocusGrantToken(), mRemoteInterface);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -507,7 +506,7 @@ public class SurfaceControlViewHost {
|
||||
* @hide
|
||||
*/
|
||||
public IBinder getFocusGrantToken() {
|
||||
return mWm.getFocusGrantToken();
|
||||
return mWm.getFocusGrantToken(getWindowToken().asBinder());
|
||||
}
|
||||
|
||||
private void addWindowToken(WindowManager.LayoutParams attrs) {
|
||||
|
||||
@@ -106,8 +106,22 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
mConfiguration.setTo(configuration);
|
||||
}
|
||||
|
||||
IBinder getFocusGrantToken() {
|
||||
return mFocusGrantToken;
|
||||
IBinder getFocusGrantToken(IBinder window) {
|
||||
synchronized (this) {
|
||||
// This can only happen if someone requested the focusGrantToken before setView was
|
||||
// called for the SCVH. In that case, use the root focusGrantToken since this will be
|
||||
// the same token sent to WMS for the root window once setView is called.
|
||||
if (mStateForWindow.isEmpty()) {
|
||||
return mFocusGrantToken;
|
||||
}
|
||||
State state = mStateForWindow.get(window);
|
||||
if (state != null) {
|
||||
return state.mFocusGrantToken;
|
||||
}
|
||||
}
|
||||
|
||||
Log.w(TAG, "Failed to get focusGrantToken. Returning null token");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
android:showWhenLocked="true"/>
|
||||
<activity android:name="android.view.cts.surfacevalidator.CapturedActivity"/>
|
||||
|
||||
<activity android:name="com.android.server.wm.SurfaceControlViewHostTests$TestActivity" />
|
||||
|
||||
<service android:name="android.view.cts.surfacevalidator.LocalMediaProjectionService"
|
||||
android:foregroundServiceType="mediaProjection"
|
||||
android:enabled="true">
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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.server.wm;
|
||||
|
||||
import static android.Manifest.permission.ACCESS_SURFACE_FLINGER;
|
||||
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
|
||||
import static android.server.wm.CtsWindowInfoUtils.waitForWindowVisible;
|
||||
import static android.server.wm.CtsWindowInfoUtils.waitForWindowFocus;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.view.Gravity;
|
||||
import android.view.IWindow;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerGlobal;
|
||||
import android.view.WindowlessWindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.rule.ActivityTestRule;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@RunWith(WindowTestRunner.class)
|
||||
public class SurfaceControlViewHostTests {
|
||||
private final ActivityTestRule<TestActivity> mActivityRule = new ActivityTestRule<>(
|
||||
TestActivity.class);
|
||||
private Instrumentation mInstrumentation;
|
||||
private TestActivity mActivity;
|
||||
|
||||
private View mView1;
|
||||
private View mView2;
|
||||
private SurfaceControlViewHost mScvh1;
|
||||
private SurfaceControlViewHost mScvh2;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
|
||||
// ACCESS_SURFACE_FLINGER is necessary to call waitForWindow
|
||||
// INTERNAL_SYSTEM_WINDOW is necessary to add SCVH with no host parent
|
||||
mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(ACCESS_SURFACE_FLINGER,
|
||||
INTERNAL_SYSTEM_WINDOW);
|
||||
mActivity = mActivityRule.launchActivity(null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFocusWithMultipleWindows() throws InterruptedException, RemoteException {
|
||||
SurfaceControl sc = new SurfaceControl.Builder()
|
||||
.setName("SurfaceControlViewHostTests")
|
||||
.setCallsite("requestFocusWithMultipleWindows")
|
||||
.build();
|
||||
mView1 = new Button(mActivity);
|
||||
mView2 = new Button(mActivity);
|
||||
|
||||
mActivity.runOnUiThread(() -> {
|
||||
TestWindowlessWindowManager wwm = new TestWindowlessWindowManager(
|
||||
mActivity.getResources().getConfiguration(), sc, null);
|
||||
|
||||
try {
|
||||
mActivity.attachToSurfaceView(sc);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
mScvh1 = new SurfaceControlViewHost(mActivity, mActivity.getDisplay(),
|
||||
wwm, "requestFocusWithMultipleWindows");
|
||||
mScvh2 = new SurfaceControlViewHost(mActivity, mActivity.getDisplay(),
|
||||
wwm, "requestFocusWithMultipleWindows");
|
||||
|
||||
|
||||
mView1.setBackgroundColor(Color.RED);
|
||||
mView2.setBackgroundColor(Color.BLUE);
|
||||
|
||||
WindowManager.LayoutParams lp1 = new WindowManager.LayoutParams(200, 200,
|
||||
TYPE_APPLICATION, 0, PixelFormat.OPAQUE);
|
||||
WindowManager.LayoutParams lp2 = new WindowManager.LayoutParams(100, 100,
|
||||
TYPE_APPLICATION, 0, PixelFormat.OPAQUE);
|
||||
mScvh1.setView(mView1, lp1);
|
||||
mScvh2.setView(mView2, lp2);
|
||||
});
|
||||
|
||||
assertTrue("Failed to wait for view1", waitForWindowVisible(mView1));
|
||||
assertTrue("Failed to wait for view2", waitForWindowVisible(mView2));
|
||||
|
||||
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
|
||||
mScvh1.getFocusGrantToken(), true);
|
||||
assertTrue("Failed to gain focus for view1", waitForWindowFocus(mView1, true));
|
||||
|
||||
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
|
||||
mScvh2.getFocusGrantToken(), true);
|
||||
assertTrue("Failed to gain focus for view2", waitForWindowFocus(mView2, true));
|
||||
}
|
||||
|
||||
private static class TestWindowlessWindowManager extends WindowlessWindowManager {
|
||||
private final SurfaceControl mRoot;
|
||||
|
||||
TestWindowlessWindowManager(Configuration c, SurfaceControl rootSurface,
|
||||
IBinder hostInputToken) {
|
||||
super(c, rootSurface, hostInputToken);
|
||||
mRoot = rootSurface;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SurfaceControl getParentSurface(IWindow window,
|
||||
WindowManager.LayoutParams attrs) {
|
||||
return mRoot;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestActivity extends Activity implements SurfaceHolder.Callback {
|
||||
private SurfaceView mSurfaceView;
|
||||
private final CountDownLatch mSvReadyLatch = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final FrameLayout content = new FrameLayout(this);
|
||||
mSurfaceView = new SurfaceView(this);
|
||||
mSurfaceView.setBackgroundColor(Color.BLACK);
|
||||
mSurfaceView.setZOrderOnTop(true);
|
||||
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(500, 500,
|
||||
Gravity.LEFT | Gravity.TOP);
|
||||
content.addView(mSurfaceView, lp);
|
||||
setContentView(content);
|
||||
mSurfaceView.getHolder().addCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
||||
mSvReadyLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width,
|
||||
int height) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
|
||||
}
|
||||
|
||||
public void attachToSurfaceView(SurfaceControl sc) throws InterruptedException {
|
||||
mSvReadyLatch.await();
|
||||
new SurfaceControl.Transaction().reparent(sc, mSurfaceView.getSurfaceControl())
|
||||
.show(sc).apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user