getDisplayDecorationSupport: return more detailed info

Call the updated native version of getDisplayDecorationSupport (added in
I961051c0a660b596039ac04b546040764ee20d34), and convert the NDK struct
into a Java class. Depend on the graphics AIDLs, which now have Java
backends. A future CL will update SysUI to call the new API.

Add a PixelFormat for R_8 to correspond to the native version. This will
allow SysUI to use COLOR_MODE_A8 when the HAL reports R_8.

If64fd6924960f592b7a211371bc2ca6536ae34f7 demonstrates using this.

Bug: 216644902
Test: manual
Change-Id: I0e34c6d6e369fda0a96231ab38c3bd5f3bfe3e06
diff --git a/Android.bp b/Android.bp
index 7d02d7d..ee5db70 100644
--- a/Android.bp
+++ b/Android.bp
@@ -109,6 +109,7 @@
         ":platform-compat-native-aidl",
 
         // AIDL sources from external directories
+        ":android.hardware.graphics.common-V3-java-source",
         ":android.hardware.security.keymint-V1-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
         ":android.hardware.tv.tuner-V1-java-source",
@@ -288,6 +289,7 @@
             // TODO: remove when moved to the below package
             "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
+            "hardware/interfaces/graphics/common/aidl",
         ],
     },
     dxflags: [
@@ -537,6 +539,7 @@
             // TODO: remove when moved to the below package
             "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
+            "hardware/interfaces/graphics/common/aidl",
         ],
     },
     // These are libs from framework-internal-utils that are required (i.e. being referenced)
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index eefa1d3..623f38e 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -1214,17 +1214,6 @@
     }
 
     /**
-     * Returns whether the specified display supports DISPLAY_DECORATION.
-     *
-     * @param displayId The display to query support.
-     *
-     * @hide
-     */
-    public boolean getDisplayDecorationSupport(int displayId) {
-        return mGlobal.getDisplayDecorationSupport(displayId);
-    }
-
-    /**
      * Returns the user preference for "Match content frame rate".
      * <p>
      * Never: Even if the app requests it, the device will never try to match its output to the
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index af8ec27..7e7a648 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -32,6 +32,7 @@
 import android.graphics.ColorSpace;
 import android.graphics.Point;
 import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.graphics.common.DisplayDecorationSupport;
 import android.media.projection.IMediaProjection;
 import android.media.projection.MediaProjection;
 import android.os.Handler;
@@ -812,13 +813,13 @@
     }
 
     /**
-     * Report whether the display supports DISPLAY_DECORATION.
+     * Report whether/how the display supports DISPLAY_DECORATION.
      *
      * @param displayId The display whose support is being queried.
      *
      * @hide
      */
-    public boolean getDisplayDecorationSupport(int displayId) {
+    public DisplayDecorationSupport getDisplayDecorationSupport(int displayId) {
         try {
             return mDm.getDisplayDecorationSupport(displayId);
         } catch (RemoteException ex) {
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index b3af52b..ddd18f4 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -22,6 +22,7 @@
 import android.hardware.display.BrightnessConfiguration;
 import android.hardware.display.BrightnessInfo;
 import android.hardware.display.Curve;
+import android.hardware.graphics.common.DisplayDecorationSupport;
 import android.hardware.display.IDisplayManagerCallback;
 import android.hardware.display.IVirtualDisplayCallback;
 import android.hardware.display.VirtualDisplayConfig;
@@ -183,5 +184,5 @@
     int getRefreshRateSwitchingType();
 
     // Query for DISPLAY_DECORATION support.
-    boolean getDisplayDecorationSupport(int displayId);
+    DisplayDecorationSupport getDisplayDecorationSupport(int displayId);
 }
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 246a8c9..7d8e998 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -42,6 +42,7 @@
 import android.hardware.display.DeviceProductInfo;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.graphics.common.DisplayDecorationSupport;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1856,6 +1857,19 @@
     }
 
     /**
+     * Returns whether/how the specified display supports DISPLAY_DECORATION.
+     *
+     * Composition.DISPLAY_DECORATION is a special layer type which is used to
+     * render the screen decorations (i.e. antialiased rounded corners and
+     * cutouts) while taking advantage of specific hardware.
+     *
+     * @hide
+     */
+    public DisplayDecorationSupport getDisplayDecorationSupport() {
+        return mGlobal.getDisplayDecorationSupport(mDisplayId);
+    }
+
+    /**
      * A mode supported by a given display.
      *
      * @see Display#getSupportedModes()
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d3061e2..3cd1e0f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -49,6 +49,7 @@
 import android.hardware.display.DeviceProductInfo;
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
+import android.hardware.graphics.common.DisplayDecorationSupport;
 import android.os.Build;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -235,7 +236,8 @@
             float shadowRadius);
     private static native void nativeSetGlobalShadowSettings(@Size(4) float[] ambientColor,
             @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius);
-    private static native boolean nativeGetDisplayDecorationSupport(IBinder displayToken);
+    private static native DisplayDecorationSupport nativeGetDisplayDecorationSupport(
+            IBinder displayToken);
 
     private static native void nativeSetFrameRate(long transactionObj, long nativeObject,
             float frameRate, int compatibility, int changeFrameRateStrategy);
@@ -2694,16 +2696,18 @@
     }
 
     /**
-     * Returns whether a display supports DISPLAY_DECORATION.
+     * Returns whether/how a display supports DISPLAY_DECORATION.
      *
      * @param displayToken
      *      The token for the display.
      *
-     * @return Whether the display supports DISPLAY_DECORATION.
+     * @return A class describing how the display supports DISPLAY_DECORATION or null if it does
+     * not.
      *
+     * TODO (b/218524164): Move this out of SurfaceControl.
      * @hide
      */
-    public static boolean getDisplayDecorationSupport(IBinder displayToken) {
+    public static DisplayDecorationSupport getDisplayDecorationSupport(IBinder displayToken) {
         return nativeGetDisplayDecorationSupport(displayToken);
     }
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 2488b57..336161c 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -245,6 +245,13 @@
     jmethodID onTransactionCommitted;
 } gTransactionCommittedListenerClassInfo;
 
+static struct {
+    jclass clazz;
+    jmethodID ctor;
+    jfieldID format;
+    jfieldID alphaInterpretation;
+} gDisplayDecorationSupportInfo;
+
 class JNamedColorSpace {
 public:
     // ColorSpace.Named.SRGB.ordinal() = 0;
@@ -1792,13 +1799,29 @@
     client->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
 }
 
-static jboolean nativeGetDisplayDecorationSupport(JNIEnv* env, jclass clazz,
-        jobject displayTokenObject) {
+static jobject nativeGetDisplayDecorationSupport(JNIEnv* env, jclass clazz,
+                                                 jobject displayTokenObject) {
     sp<IBinder> displayToken(ibinderForJavaObject(env, displayTokenObject));
     if (displayToken == nullptr) {
-        return JNI_FALSE;
+        return nullptr;
     }
-    return static_cast<jboolean>(SurfaceComposerClient::getDisplayDecorationSupport(displayToken));
+    const auto support = SurfaceComposerClient::getDisplayDecorationSupport(displayToken);
+    if (!support) {
+        return nullptr;
+    }
+
+    jobject jDisplayDecorationSupport =
+            env->NewObject(gDisplayDecorationSupportInfo.clazz, gDisplayDecorationSupportInfo.ctor);
+    if (jDisplayDecorationSupport == nullptr) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+        return nullptr;
+    }
+
+    env->SetIntField(jDisplayDecorationSupport, gDisplayDecorationSupportInfo.format,
+                     static_cast<jint>(support.value().format));
+    env->SetIntField(jDisplayDecorationSupport, gDisplayDecorationSupportInfo.alphaInterpretation,
+                     static_cast<jint>(support.value().alphaInterpretation));
+    return jDisplayDecorationSupport;
 }
 
 static jlong nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
@@ -2131,7 +2154,8 @@
             (void*)nativeMirrorSurface },
     {"nativeSetGlobalShadowSettings", "([F[FFFF)V",
             (void*)nativeSetGlobalShadowSettings },
-    {"nativeGetDisplayDecorationSupport", "(Landroid/os/IBinder;)Z",
+    {"nativeGetDisplayDecorationSupport",
+            "(Landroid/os/IBinder;)Landroid/hardware/graphics/common/DisplayDecorationSupport;",
             (void*)nativeGetDisplayDecorationSupport},
     {"nativeGetHandle", "(J)J",
             (void*)nativeGetHandle },
@@ -2390,6 +2414,17 @@
     gTransactionCommittedListenerClassInfo.onTransactionCommitted =
             GetMethodIDOrDie(env, transactionCommittedListenerClazz, "onTransactionCommitted",
                              "()V");
+
+    jclass displayDecorationSupportClazz =
+            FindClassOrDie(env, "android/hardware/graphics/common/DisplayDecorationSupport");
+    gDisplayDecorationSupportInfo.clazz = MakeGlobalRefOrDie(env, displayDecorationSupportClazz);
+    gDisplayDecorationSupportInfo.ctor =
+            GetMethodIDOrDie(env, displayDecorationSupportClazz, "<init>", "()V");
+    gDisplayDecorationSupportInfo.format =
+            GetFieldIDOrDie(env, displayDecorationSupportClazz, "format", "I");
+    gDisplayDecorationSupportInfo.alphaInterpretation =
+            GetFieldIDOrDie(env, displayDecorationSupportClazz, "alphaInterpretation", "I");
+
     return err;
 }
 
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index dde757b..3ec5b9c 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -29,7 +29,7 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({RGBA_8888, RGBX_8888, RGBA_F16, RGBA_1010102, RGB_888, RGB_565})
+    @IntDef({RGBA_8888, RGBX_8888, RGBA_F16, RGBA_1010102, RGB_888, RGB_565, R_8})
     public @interface Format { }
 
     // NOTE: these constants must match the values from graphics/common/x.x/types.hal
@@ -93,6 +93,9 @@
     /** @hide */
     public static final int HSV_888 = 0x37;
 
+    /** @hide */
+    public static final int R_8 = 0x38;
+
     /**
      * @deprecated use {@link android.graphics.ImageFormat#JPEG
      * ImageFormat.JPEG} instead.
@@ -142,6 +145,10 @@
                 info.bitsPerPixel = 64;
                 info.bytesPerPixel = 8;
                 break;
+            case R_8:
+                info.bitsPerPixel = 8;
+                info.bytesPerPixel = 1;
+                break;
             default:
                 throw new IllegalArgumentException("unknown pixel format " + format);
         }
@@ -235,6 +242,8 @@
                 return "HSV_888";
             case JPEG:
                 return "JPEG";
+            case R_8:
+                return "R_8";
             default:
                 return Integer.toString(format);
         }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 7f1482e..f5001102 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -78,6 +78,7 @@
 import android.hardware.display.IVirtualDisplayCallback;
 import android.hardware.display.VirtualDisplayConfig;
 import android.hardware.display.WifiDisplayStatus;
+import android.hardware.graphics.common.DisplayDecorationSupport;
 import android.hardware.input.InputManagerInternal;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionManager;
@@ -1860,10 +1861,10 @@
         return mDisplayModeDirector.getModeSwitchingType();
     }
 
-    private boolean getDisplayDecorationSupportInternal(int displayId) {
+    private DisplayDecorationSupport getDisplayDecorationSupportInternal(int displayId) {
         final IBinder displayToken = getDisplayToken(displayId);
         if (null == displayToken) {
-            return false;
+            return null;
         }
         return SurfaceControl.getDisplayDecorationSupport(displayToken);
     }
@@ -3550,7 +3551,7 @@
         }
 
         @Override // Binder call
-        public boolean getDisplayDecorationSupport(int displayId) {
+        public DisplayDecorationSupport getDisplayDecorationSupport(int displayId) {
             final long token = Binder.clearCallingIdentity();
             try {
                 return getDisplayDecorationSupportInternal(displayId);