diff options
author | Bo Hu <bohu@google.com> | 2023-11-01 09:32:19 -0700 |
---|---|---|
committer | Bo Hu <bohu@google.com> | 2023-11-01 09:37:41 -0700 |
commit | 53d914d54d85d97961514e6b8d257457129e7889 (patch) | |
tree | 9cc815f41a28d4ed85a37cf83e65ecde8bee90cc | |
parent | d8bec145ae59c2265c61301ac7f0c45b89103b93 (diff) | |
download | goldfish-53d914d54d85d97961514e6b8d257457129e7889.tar.gz |
multidisplay: call surfaceflinger to set display
The resizable emulator needs to change display frequently,
and multidisplay is enhanced to do that.
This cl adds "SET_DISPLAY" command to multidisplay and
calls surfaceflinger to do that.
necessary permissions are added to achieve this.
Bug: 308443736
Change-Id: I1c0c54eb152d26a79a91115a826c64131da1bb5e
5 files changed, 90 insertions, 6 deletions
diff --git a/MultiDisplayProvider/AndroidManifest.xml b/MultiDisplayProvider/AndroidManifest.xml index 3b3b1e34..5c203bdc 100644 --- a/MultiDisplayProvider/AndroidManifest.xml +++ b/MultiDisplayProvider/AndroidManifest.xml @@ -20,7 +20,11 @@ package="com.android.emulator.multidisplay" android:sharedUserId="android.uid.system" > + <uses-permission android:name="android.permission.HARDWARE_TEST" /> + <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" /> + <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> <uses-sdk android:minSdkVersion="19" /> + <application android:label="@string/app_name" android:persistent="true"> <receiver android:name=".MultiDisplayServiceReceiver" diff --git a/MultiDisplayProvider/jni/com_android_emulator_multidisplay.cpp b/MultiDisplayProvider/jni/com_android_emulator_multidisplay.cpp index 10e92828..26c7a439 100644 --- a/MultiDisplayProvider/jni/com_android_emulator_multidisplay.cpp +++ b/MultiDisplayProvider/jni/com_android_emulator_multidisplay.cpp @@ -43,6 +43,7 @@ static const uint8_t ADD = 1; static const uint8_t DEL = 2; static const uint8_t QUERY = 3; static const uint8_t BIND = 4; +static const uint8_t SET_DISPLAY = 0x10; static void fillMsg(std::vector<uint8_t>& buf, uint8_t cmd, uint8_t* data, uint32_t size) { // msg format is size(4B) + cmd(1B) + data(size B) @@ -125,6 +126,14 @@ static bool nativeReadPipe(JNIEnv* env, jobject obj, jintArray arr) { std::vector<uint8_t> args(length, 0); qemu_pipe_read_fully(gFd, args.data(), (size_t)length); switch(args[0]) { + case SET_DISPLAY: + ALOGV("received setdisplay event"); + *arrp = SET_DISPLAY; + for (int i = 1; i < 6; i++) { + *(arrp + i) = *(uint32_t*)(&args[(i - 1) * 4 + 1]); + } + env->ReleaseIntArrayElements(arr, arrp, JNI_COMMIT); + break; case ADD: { ALOGV("received add event"); *arrp = ADD; diff --git a/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java b/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java index 41da9237..d78cc4ee 100644 --- a/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java +++ b/MultiDisplayProvider/src/com/android/emulator/multidisplay/MultiDisplayService.java @@ -17,15 +17,20 @@ package com.android.emulator.multidisplay; import android.app.Service; +import android.hardware.display.DisplayManager; +import android.hardware.display.VirtualDisplay; import android.content.Intent; import android.os.Handler; import android.os.IBinder; +import android.os.Messenger; +import android.os.Parcel; +import android.os.RemoteException; +import android.os.ServiceManager; import android.util.DebugUtils; import android.util.Log; -import android.hardware.display.DisplayManager; -import android.hardware.display.VirtualDisplay; import android.view.Surface; +import java.lang.Thread; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -33,8 +38,6 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import android.os.Messenger; - public final class MultiDisplayService extends Service { private static final String TAG = "MultiDisplayService"; private static final String DISPLAY_NAME = "Emulator 2D Display"; @@ -47,6 +50,10 @@ public final class MultiDisplayService extends Service { private static final int MAX_DISPLAYS = 10; private static final int ADD = 1; private static final int DEL = 2; + // the following is used by resizabel to set display + // intentionally shifted 4 bits to avoid conflicting + // with existing multidisplay functions + private static final int SET_DISPLAY = 0x10; private static final int FLAGS = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | @@ -55,6 +62,8 @@ public final class MultiDisplayService extends Service { 1 << 6 |//DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH 1 << 9; //DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; + private static final String SURFACE_COMPOSER_INTERFACE_KEY = "android.ui.ISurfaceComposer"; + private IBinder mSurfaceFlinger; private DisplayManager mDisplayManager; private VirtualDisplay mVirtualDisplay[]; private Surface mSurface[]; @@ -130,7 +139,7 @@ public final class MultiDisplayService extends Service { @Override public void onCreate() { - Log.d(TAG, "Creating service"); + Log.i(TAG, "Creating service"); super.onCreate(); @@ -359,12 +368,16 @@ public final class MultiDisplayService extends Service { while(nativeOpen() <= 0) { Log.e(TAG, "failed to open multiDisplay pipe, retry"); } + Log.d(TAG, "success open multiDisplay pipe"); while(true) { + Log.d(TAG, "waiting to read pipe"); int[] array = {0, 0, 0, 0, 0, 0}; if (!nativeReadPipe(array)) { + Log.e(TAG, "failed and try again"); continue; } - Log.v(TAG, "run(): array= " + Arrays.toString(array)); + Log.d(TAG, "have read something from pipe"); + Log.d(TAG, "run(): array= " + Arrays.toString(array)); switch (array[0]) { case ADD: { for (int j = 0; j < 6; j++) { @@ -392,6 +405,34 @@ public final class MultiDisplayService extends Service { deleteVirtualDisplay(i); break; } + case SET_DISPLAY: { + for (int j = 0; j < 6; j++) { + Log.d(TAG, "SET_DISPLAY received " + array[j]); + } + if (mSurfaceFlinger == null) { + Log.d(TAG, "obtain surfaceflinger " ); + mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger"); + } + if (mSurfaceFlinger != null) { + int i = array[1]; + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY); + data.writeInt(i); + try { + if (i >=0) { + mSurfaceFlinger.transact(1035, data, null, 0 /* flags */); + Log.d(TAG, "setting display to " + i); + } else { + Log.e(TAG, "invalid display id " + i); + } + } catch (RemoteException e) { + Log.e(TAG, "Could not set display:" + e.toString()); + } + } else { + Log.e(TAG, "cannot get SurfaceFlinger service"); + } + break; + } // TODO(b/231763427): implement LIST } } diff --git a/data/etc/permissions/privapp-permissions-multidisplay.xml b/data/etc/permissions/privapp-permissions-multidisplay.xml new file mode 100644 index 00000000..7e79a604 --- /dev/null +++ b/data/etc/permissions/privapp-permissions-multidisplay.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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 + --> +<!-- +This XML file declares which signature|privileged permissions should be granted to privileged +applications on GMS or Google-branded devices. +It allows additional grants on top of privapp-permissions-platform.xml +--> +<permissions> + <privapp-permissions package="com.android.emulator.multidisplay"> + <permission name="android.permission.HARDWARE_TEST"/> + <permission name="android.permission.INTERNAL_SYSTEM_WINDOW"/> + <permission name="android.permission.ACCESS_SURFACE_FLINGER"/> + </privapp-permissions> +</permissions> + diff --git a/vendor_common.mk b/vendor_common.mk index d4cbb318..a0d5479f 100644 --- a/vendor_common.mk +++ b/vendor_common.mk @@ -338,6 +338,7 @@ PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.software.autofill.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.autofill.xml \ frameworks/native/data/etc/android.software.verified_boot.xml:${TARGET_COPY_OUT_PRODUCT}/etc/permissions/android.software.verified_boot.xml \ device/generic/goldfish/data/etc/permissions/privapp-permissions-goldfish.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/permissions/privapp-permissions-goldfish.xml \ + device/generic/goldfish/data/etc/permissions/privapp-permissions-multidisplay.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/etc/permissions/privapp-permissions-multidisplay.xml \ ifneq ($(EMULATOR_DISABLE_RADIO),true) # Android TV ingests this file, but declares its own set of hardware permissions. |