diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java index 80182d26003d7..dc7573e204389 100644 --- a/services/companion/java/com/android/server/companion/virtual/InputController.java +++ b/services/companion/java/com/android/server/companion/virtual/InputController.java @@ -37,6 +37,7 @@ import android.util.ArrayMap; import android.util.Slog; import android.view.Display; import android.view.InputDevice; +import android.view.WindowManager; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -83,22 +84,26 @@ class InputController { private final NativeWrapper mNativeWrapper; private final DisplayManagerInternal mDisplayManagerInternal; private final InputManagerInternal mInputManagerInternal; + private final WindowManager mWindowManager; private final DeviceCreationThreadVerifier mThreadVerifier; - InputController(@NonNull Object lock, @NonNull Handler handler) { - this(lock, new NativeWrapper(), handler, + InputController(@NonNull Object lock, @NonNull Handler handler, + @NonNull WindowManager windowManager) { + this(lock, new NativeWrapper(), handler, windowManager, // Verify that virtual devices are not created on the handler thread. () -> !handler.getLooper().isCurrentThread()); } @VisibleForTesting InputController(@NonNull Object lock, @NonNull NativeWrapper nativeWrapper, - @NonNull Handler handler, @NonNull DeviceCreationThreadVerifier threadVerifier) { + @NonNull Handler handler, @NonNull WindowManager windowManager, + @NonNull DeviceCreationThreadVerifier threadVerifier) { mLock = lock; mHandler = handler; mNativeWrapper = nativeWrapper; mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); + mWindowManager = windowManager; mThreadVerifier = threadVerifier; } @@ -209,6 +214,15 @@ class InputController { mInputManagerInternal.setDisplayEligibilityForPointerCapture(displayId, isEligible); } + void setLocalIme(int displayId) { + // WM throws a SecurityException if the display is untrusted. + if ((mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED) + == Display.FLAG_TRUSTED) { + mWindowManager.setDisplayImePolicy(displayId, + WindowManager.DISPLAY_IME_POLICY_LOCAL); + } + } + @GuardedBy("mLock") private void updateActivePointerDisplayIdLocked() { InputDeviceDescriptor mostRecentlyCreatedMouse = null; diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index 9802b9783da26..638b3aeef544b 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -62,6 +62,7 @@ import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import android.view.Display; +import android.view.WindowManager; import android.widget.Toast; import android.window.DisplayWindowPolicyController; @@ -167,7 +168,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams = params; if (inputController == null) { mInputController = new InputController( - mVirtualDeviceLock, context.getMainThreadHandler()); + mVirtualDeviceLock, + context.getMainThreadHandler(), + context.getSystemService(WindowManager.class)); } else { mInputController = inputController; } @@ -537,6 +540,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mInputController.setPointerAcceleration(1f, displayId); mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false, displayId); + mInputController.setLocalIme(displayId); // Since we're being called in the middle of the display being created, we post a // task to grab the wakelock instead of doing it synchronously here, to avoid diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java index 77cbb3a6398c7..5d9d7656aa5bb 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java @@ -34,6 +34,9 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.Display; import android.view.DisplayInfo; +import android.view.WindowManager; + +import androidx.test.InstrumentationRegistry; import com.android.server.LocalServices; @@ -79,7 +82,9 @@ public class InputControllerTest { // Allow virtual devices to be created on the looper thread for testing. final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true; mInputController = new InputController(new Object(), mNativeWrapperMock, - new Handler(TestableLooper.get(this).getLooper()), threadVerifier); + new Handler(TestableLooper.get(this).getLooper()), + InstrumentationRegistry.getTargetContext().getSystemService(WindowManager.class), + threadVerifier); } @Test diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java index cbb9fd7c30dd6..f9671e56fe128 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java @@ -77,6 +77,7 @@ import android.testing.TestableLooper; import android.util.ArraySet; import android.view.DisplayInfo; import android.view.KeyEvent; +import android.view.WindowManager; import androidx.test.InstrumentationRegistry; @@ -208,7 +209,8 @@ public class VirtualDeviceManagerServiceTest { // Allow virtual devices to be created on the looper thread for testing. final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true; mInputController = new InputController(new Object(), mNativeWrapperMock, - new Handler(TestableLooper.get(this).getLooper()), threadVerifier); + new Handler(TestableLooper.get(this).getLooper()), + mContext.getSystemService(WindowManager.class), threadVerifier); mAssociationInfo = new AssociationInfo(1, 0, null, MacAddress.BROADCAST_ADDRESS, "", null, true, false, 0, 0);