Merge "HDR info listener" into sc-dev

This commit is contained in:
John Reck
2021-04-02 20:21:51 +00:00
committed by Android (Google) Code Review
5 changed files with 271 additions and 1 deletions

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2021 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 android.view;
import android.annotation.RequiresPermission;
import android.os.IBinder;
import android.util.ArrayMap;
import libcore.util.NativeAllocationRegistry;
import java.util.Objects;
/**
* Allows for the monitoring of layers with HDR content
*
* @hide */
public abstract class SurfaceControlHdrLayerInfoListener {
private static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
SurfaceControlHdrLayerInfoListener.class.getClassLoader(), nGetDestructor());
/**
* Callback when the HDR information about the given display has changed
*
* @param displayToken The display this callback is about
* @param numberOfHdrLayers How many HDR layers are visible on the display
* @param maxW The width of the HDR layer with the largest area
* @param maxH The height of the HDR layer with the largest area
* @param flags Additional metadata flags, currently always 0
* TODO(b/182312559): Add some flags
*
* @hide */
public abstract void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers,
int maxW, int maxH, int flags);
/**
* Registers this as an HDR info listener on the provided display
* @param displayToken
*/
@RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
public void register(IBinder displayToken) {
Objects.requireNonNull(displayToken);
synchronized (this) {
if (mRegisteredListeners.containsKey(displayToken)) {
return;
}
long nativePtr = nRegister(displayToken);
Runnable destructor = sRegistry.registerNativeAllocation(this, nativePtr);
mRegisteredListeners.put(displayToken, destructor);
}
}
/**
* Unregisters this as an HDR info listener on the provided display
* @param displayToken
*/
@RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
public void unregister(IBinder displayToken) {
Objects.requireNonNull(displayToken);
final Runnable destructor;
synchronized (this) {
destructor = mRegisteredListeners.remove(displayToken);
}
if (destructor != null) {
destructor.run();
}
}
/**
* Unregisters this on all previously registered displays
*/
@RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
public void unregisterAll() {
final ArrayMap<IBinder, Runnable> toDestroy;
synchronized (this) {
toDestroy = mRegisteredListeners;
mRegisteredListeners = new ArrayMap<>();
}
for (Runnable destructor : toDestroy.values()) {
destructor.run();
}
}
private ArrayMap<IBinder, Runnable> mRegisteredListeners = new ArrayMap<>();
private static native long nGetDestructor();
private native long nRegister(IBinder displayToken);
}

View File

@@ -70,7 +70,10 @@ cc_library_shared {
"libz",
],
static_libs: ["libnativehelper_lazy", "libziparchive_for_incfs", ],
static_libs: [
"libnativehelper_lazy",
"libziparchive_for_incfs",
],
export_include_dirs: [
".",
@@ -121,6 +124,7 @@ cc_library_shared {
"android_view_Surface.cpp",
"android_view_SurfaceControl.cpp",
"android_view_SurfaceControlFpsListener.cpp",
"android_view_SurfaceControlHdrLayerInfoListener.cpp",
"android_graphics_BLASTBufferQueue.cpp",
"android_view_SurfaceSession.cpp",
"android_view_TextureView.cpp",

View File

@@ -122,6 +122,7 @@ extern int register_android_view_InputWindowHandle(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
extern int register_android_view_SurfaceControl(JNIEnv* env);
extern int register_android_view_SurfaceControlFpsListener(JNIEnv* env);
extern int register_android_view_SurfaceControlHdrLayerInfoListener(JNIEnv* env);
extern int register_android_view_SurfaceSession(JNIEnv* env);
extern int register_android_view_CompositionSamplingListener(JNIEnv* env);
extern int register_android_view_TextureView(JNIEnv* env);
@@ -1515,6 +1516,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_SurfaceControl),
REG_JNI(register_android_view_SurfaceControlFpsListener),
REG_JNI(register_android_view_SurfaceControlHdrLayerInfoListener),
REG_JNI(register_android_view_SurfaceSession),
REG_JNI(register_android_view_CompositionSamplingListener),
REG_JNI(register_android_view_TextureView),

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2021 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.
*/
#define LOG_TAG "SurfaceControlHdrLayerInfoListener"
#include <android/gui/BnHdrLayerInfoListener.h>
#include <android_runtime/Log.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <log/log.h>
#include <nativehelper/JNIHelp.h>
#include <utils/RefBase.h>
#include "android_util_Binder.h"
#include "core_jni_helpers.h"
namespace android {
namespace {
struct {
jclass mClass;
jmethodID mOnHdrInfoChanged;
} gListenerClassInfo;
struct SurfaceControlHdrLayerInfoListener : public gui::BnHdrLayerInfoListener {
SurfaceControlHdrLayerInfoListener(JNIEnv* env, jobject listener, jobject displayToken)
: mListener(env->NewGlobalRef(listener)), mDisplayToken(env->NewGlobalRef(displayToken)) {
LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mVm) != JNI_OK, "Failed to GetJavaVm");
}
binder::Status onHdrLayerInfoChanged(int numberOfHdrLayers, int maxW, int maxH,
int flags) override {
JNIEnv* env = requireEnv();
env->CallVoidMethod(mListener, gListenerClassInfo.mOnHdrInfoChanged, mDisplayToken,
numberOfHdrLayers, maxW, maxH, flags);
if (env->ExceptionCheck()) {
ALOGE("SurfaceControlHdrLayerInfoListener.onHdrInfoChanged() failed.");
LOGE_EX(env);
env->ExceptionClear();
}
return binder::Status::ok();
}
status_t startListening() {
auto token = ibinderForJavaObject(requireEnv(), mDisplayToken);
return SurfaceComposerClient::addHdrLayerInfoListener(token, this);
}
status_t stopListening() {
auto token = ibinderForJavaObject(requireEnv(), mDisplayToken);
return SurfaceComposerClient::removeHdrLayerInfoListener(token, this);
}
protected:
virtual ~SurfaceControlHdrLayerInfoListener() {
JNIEnv* env = requireEnv();
env->DeleteGlobalRef(mListener);
env->DeleteGlobalRef(mDisplayToken);
}
JNIEnv* requireEnv() {
JNIEnv* env = nullptr;
if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
if (mVm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
}
}
return env;
}
private:
jobject mListener;
jobject mDisplayToken;
JavaVM* mVm;
};
jlong nRegister(JNIEnv* env, jobject jthis, jobject jbinderToken) {
auto callback = sp<SurfaceControlHdrLayerInfoListener>::make(env, jthis, jbinderToken);
status_t err = callback->startListening();
if (err != OK) {
auto errStr = statusToString(err);
jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
"Failed to register HdrLayerInfoListener, err = %d (%s)", err,
errStr.c_str());
return 0;
}
SurfaceControlHdrLayerInfoListener* ret = callback.get();
ret->incStrong(0);
return static_cast<jlong>(reinterpret_cast<intptr_t>(ret));
}
static void destroy(SurfaceControlHdrLayerInfoListener* listener) {
listener->stopListening();
listener->decStrong(0);
}
static jlong nGetDestructor(JNIEnv* env, jobject clazz) {
return static_cast<jlong>(reinterpret_cast<intptr_t>(&destroy));
}
const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{"nGetDestructor", "()J", (void*)nGetDestructor},
{"nRegister", "(Landroid/os/IBinder;)J", (void*)nRegister}};
} // namespace
int register_android_view_SurfaceControlHdrLayerInfoListener(JNIEnv* env) {
int res = jniRegisterNativeMethods(env, "android/view/SurfaceControlHdrLayerInfoListener",
gMethods, NELEM(gMethods));
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
jclass clazz = env->FindClass("android/view/SurfaceControlHdrLayerInfoListener");
gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
gListenerClassInfo.mOnHdrInfoChanged =
env->GetMethodID(clazz, "onHdrInfoChanged", "(Landroid/os/IBinder;IIII)V");
return 0;
}
} // namespace android

View File

@@ -19,7 +19,11 @@ package com.android.test.silkfx.common
import android.content.Context
import android.content.pm.ActivityInfo
import android.hardware.display.DisplayManager
import android.os.IBinder
import android.util.AttributeSet
import android.util.Log
import android.view.SurfaceControl
import android.view.SurfaceControlHdrLayerInfoListener
import android.view.Window
import android.widget.Button
import android.widget.LinearLayout
@@ -35,6 +39,7 @@ class ColorModeControls : LinearLayout, WindowObserver {
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
displayManager = context.getSystemService(DisplayManager::class.java)!!
displayId = context.getDisplayId()
displayToken = SurfaceControl.getInternalDisplayToken()
}
private var window: Window? = null
@@ -42,6 +47,7 @@ class ColorModeControls : LinearLayout, WindowObserver {
private val displayManager: DisplayManager
private var targetSdrWhitePointIndex = 0
private var displayId: Int
private var displayToken: IBinder
private val whitePoint get() = SDR_WHITE_POINTS[targetSdrWhitePointIndex]
@@ -109,6 +115,7 @@ class ColorModeControls : LinearLayout, WindowObserver {
// Imperfect, but close enough, synchronization by waiting for frame commit to set the value
viewTreeObserver.registerFrameCommitCallback {
try {
SurfaceControl.setDisplayBrightness(displayToken, level)
displayManager.setTemporaryBrightness(displayId, level)
} catch (ex: Exception) {
// Ignore a permission denied rejection - it doesn't meaningfully change much
@@ -116,9 +123,28 @@ class ColorModeControls : LinearLayout, WindowObserver {
}
}
private val listener = object : SurfaceControlHdrLayerInfoListener() {
override fun onHdrInfoChanged(
displayToken: IBinder?,
numberOfHdrLayers: Int,
maxW: Int,
maxH: Int,
flags: Int
) {
Log.d("HDRInfo", "onHdrInfoChanged: numLayer = $numberOfHdrLayers ($maxW x $maxH)" +
", flags = $flags")
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
threadedRenderer?.setColorMode(window!!.colorMode, whitePoint)
listener.register(displayToken)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
listener.unregister(displayToken)
}
}