VmLauncherApp supports the display from vm
Bug: 331708504
Test: check if the display shows
Change-Id: I18a70bb9520c91c8a26f5d64e982550b01351e4e
diff --git a/vmlauncher_app/Android.bp b/vmlauncher_app/Android.bp
index cd40448..06dcf7a 100644
--- a/vmlauncher_app/Android.bp
+++ b/vmlauncher_app/Android.bp
@@ -10,6 +10,10 @@
"androidx-constraintlayout_constraintlayout",
"androidx.appcompat_appcompat",
"com.google.android.material_material",
+ // TODO(b/330257000): will be removed when binder RPC is used
+ "android.system.virtualizationservice_internal-java",
+ // TODO(b/331708504): will be removed when AVF framework handles surface
+ "libcrosvm_android_display_service-java",
],
libs: [
"framework-virtualization.impl",
diff --git a/vmlauncher_app/AndroidManifest.xml b/vmlauncher_app/AndroidManifest.xml
index de9d094..860c03f 100644
--- a/vmlauncher_app/AndroidManifest.xml
+++ b/vmlauncher_app/AndroidManifest.xml
@@ -7,7 +7,11 @@
<uses-feature android:name="android.software.virtualization_framework" android:required="true" />
<application
android:label="VmLauncherApp">
- <activity android:name=".MainActivity" android:exported="true">
+ <activity android:name=".MainActivity"
+ android:screenOrientation="landscape"
+ android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation|uiMode"
+ android:theme="@style/MyTheme"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
index 7c927c9..2af1e2f 100644
--- a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
+++ b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
@@ -20,6 +20,10 @@
import android.app.Activity;
import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.crosvm.ICrosvmAndroidDisplayService;
+import android.system.virtualizationservice_internal.IVirtualizationServiceInternal;
import android.system.virtualmachine.VirtualMachineCustomImageConfig;
import android.util.Log;
import android.system.virtualmachine.VirtualMachine;
@@ -27,6 +31,11 @@
import android.system.virtualmachine.VirtualMachineConfig;
import android.system.virtualmachine.VirtualMachineException;
import android.system.virtualmachine.VirtualMachineManager;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.WindowManager;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import org.json.JSONArray;
import org.json.JSONException;
@@ -108,6 +117,7 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().setDecorFitsSystemWindows(false);
setContentView(R.layout.activity_main);
VirtualMachineCallback callback =
new VirtualMachineCallback() {
@@ -184,6 +194,70 @@
} catch (VirtualMachineException e) {
throw new RuntimeException(e);
}
+
+ SurfaceView surfaceView = findViewById(R.id.surface_view);
+ surfaceView
+ .getHolder()
+ .addCallback(
+ // TODO(b/331708504): it should be handled in AVF framework.
+ new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ Log.d(
+ TAG,
+ "surface size: "
+ + holder.getSurfaceFrame().flattenToString());
+ Log.d(
+ TAG,
+ "ICrosvmAndroidDisplayService.setSurface("
+ + holder.getSurface()
+ + ")");
+ runWithDisplayService(
+ (service) -> service.setSurface(holder.getSurface()));
+ }
+
+ @Override
+ public void surfaceChanged(
+ SurfaceHolder holder, int format, int width, int height) {
+ Log.d(TAG, "width: " + width + ", height: " + height);
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ Log.d(TAG, "ICrosvmAndroidDisplayService.removeSurface()");
+ runWithDisplayService((service) -> service.removeSurface());
+ }
+ });
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ // Fullscreen:
+ WindowInsetsController windowInsetsController = surfaceView.getWindowInsetsController();
+ windowInsetsController.setSystemBarsBehavior(
+ WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
+ windowInsetsController.hide(WindowInsets.Type.systemBars());
+ }
+
+ @FunctionalInterface
+ public interface RemoteExceptionCheckedFunction<T> {
+ void apply(T t) throws RemoteException;
+ }
+
+ private void runWithDisplayService(
+ RemoteExceptionCheckedFunction<ICrosvmAndroidDisplayService> func) {
+ IVirtualizationServiceInternal vs =
+ IVirtualizationServiceInternal.Stub.asInterface(
+ ServiceManager.getService("android.system.virtualizationservice"));
+ try {
+ assert vs != null;
+ Log.d(TAG, "wait for the service");
+ ICrosvmAndroidDisplayService service =
+ ICrosvmAndroidDisplayService.Stub.asInterface(vs.waitDisplayService());
+ assert service != null;
+ func.apply(service);
+ Log.d(TAG, "job done");
+ } catch (Exception e) {
+ Log.d(TAG, "error", e);
+ }
}
/** Reads data from an input stream and posts it to the output data */
diff --git a/vmlauncher_app/res/layout/activity_main.xml b/vmlauncher_app/res/layout/activity_main.xml
index 5cbda78..6cc899f 100644
--- a/vmlauncher_app/res/layout/activity_main.xml
+++ b/vmlauncher_app/res/layout/activity_main.xml
@@ -7,12 +7,10 @@
android:scrollbars="horizontal|vertical"
android:textAlignment="textStart"
tools:context=".MainActivity">
-
- <LinearLayout
+ <SurfaceView
+ android:id="@+id/surface_view"
+ android:focusable="true"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- </LinearLayout>
+ android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/vmlauncher_app/res/values/themes.xml b/vmlauncher_app/res/values/themes.xml
new file mode 100644
index 0000000..395f089
--- /dev/null
+++ b/vmlauncher_app/res/values/themes.xml
@@ -0,0 +1,14 @@
+
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <style name="MyTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar">
+ <item name="android:navigationBarColor">
+ @android:color/transparent
+ </item>
+ <item name="android:statusBarColor">
+ @android:color/transparent
+ </item>
+ <item name="android:windowLayoutInDisplayCutoutMode">
+ shortEdges
+ </item>
+ </style>
+</resources>