Add JNI and public methods for TrustedPresentationCallback
Test: TrustedPresentationCallbackTest Bug: 256993331 Change-Id: Iade93f73c55264886ef647e4fd24af614fe871d2
This commit is contained in:
@@ -51183,6 +51183,7 @@ package android.view {
|
||||
method @NonNull public android.view.SurfaceControl.Transaction addTransactionCommittedListener(@NonNull java.util.concurrent.Executor, @NonNull android.view.SurfaceControl.TransactionCommittedListener);
|
||||
method public void apply();
|
||||
method @NonNull public android.view.SurfaceControl.Transaction clearFrameRate(@NonNull android.view.SurfaceControl);
|
||||
method @NonNull public android.view.SurfaceControl.Transaction clearTrustedPresentationCallback(@NonNull android.view.SurfaceControl);
|
||||
method public void close();
|
||||
method public int describeContents();
|
||||
method @NonNull public android.view.SurfaceControl.Transaction merge(@NonNull android.view.SurfaceControl.Transaction);
|
||||
@@ -51203,6 +51204,7 @@ package android.view {
|
||||
method @NonNull public android.view.SurfaceControl.Transaction setOpaque(@NonNull android.view.SurfaceControl, boolean);
|
||||
method @NonNull public android.view.SurfaceControl.Transaction setPosition(@NonNull android.view.SurfaceControl, float, float);
|
||||
method @NonNull public android.view.SurfaceControl.Transaction setScale(@NonNull android.view.SurfaceControl, float, float);
|
||||
method @NonNull public android.view.SurfaceControl.Transaction setTrustedPresentationCallback(@NonNull android.view.SurfaceControl, @NonNull android.view.SurfaceControl.TrustedPresentationThresholds, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
|
||||
method @NonNull public android.view.SurfaceControl.Transaction setVisibility(@NonNull android.view.SurfaceControl, boolean);
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.SurfaceControl.Transaction> CREATOR;
|
||||
@@ -51212,6 +51214,10 @@ package android.view {
|
||||
method public void onTransactionCommitted();
|
||||
}
|
||||
|
||||
public static class SurfaceControl.TrustedPresentationThresholds {
|
||||
ctor public SurfaceControl.TrustedPresentationThresholds(@FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @IntRange(from=1) int);
|
||||
}
|
||||
|
||||
public class SurfaceControlViewHost {
|
||||
ctor public SurfaceControlViewHost(@NonNull android.content.Context, @NonNull android.view.Display, @Nullable android.os.IBinder);
|
||||
method @Nullable public android.view.SurfaceControlViewHost.SurfacePackage getSurfacePackage();
|
||||
|
||||
@@ -280,7 +280,12 @@ public final class SurfaceControl implements Parcelable {
|
||||
private static native void nativeSetDefaultApplyToken(IBinder token);
|
||||
private static native IBinder nativeGetDefaultApplyToken();
|
||||
private static native boolean nativeBootFinished();
|
||||
|
||||
private static native long nativeCreateTpc(TrustedPresentationCallback callback);
|
||||
private static native long getNativeTrustedPresentationCallbackFinalizer();
|
||||
private static native void nativeSetTrustedPresentationCallback(long transactionObj,
|
||||
long nativeObject, long nativeTpc, TrustedPresentationThresholds thresholds);
|
||||
private static native void nativeClearTrustedPresentationCallback(long transactionObj,
|
||||
long nativeObject);
|
||||
|
||||
/**
|
||||
* Transforms that can be applied to buffers as they are displayed to a window.
|
||||
@@ -465,6 +470,8 @@ public final class SurfaceControl implements Parcelable {
|
||||
@GuardedBy("mLock")
|
||||
private int mHeight;
|
||||
|
||||
private TrustedPresentationCallback mTrustedPresentationCallback;
|
||||
|
||||
private WeakReference<View> mLocalOwnerView;
|
||||
|
||||
static GlobalTransactionWrapper sGlobalTransaction;
|
||||
@@ -2399,6 +2406,79 @@ public final class SurfaceControl implements Parcelable {
|
||||
void onTransactionCommitted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Threshold values that are sent with
|
||||
* {@link Transaction#setTrustedPresentationCallback(SurfaceControl,
|
||||
* TrustedPresentationThresholds, Executor, Consumer)}
|
||||
*/
|
||||
public static class TrustedPresentationThresholds {
|
||||
private float mMinAlpha;
|
||||
private float mMinFractionRendered;
|
||||
private int mStabilityRequirementMs;
|
||||
|
||||
/**
|
||||
* Creates a TrustedPresentationThresholds that's used when calling
|
||||
* {@link Transaction#setTrustedPresentationCallback(SurfaceControl,
|
||||
* TrustedPresentationThresholds, Executor, Consumer)}
|
||||
*
|
||||
* @param minAlpha The min alpha the {@link SurfaceControl} is required to
|
||||
* have to be considered inside the threshold.
|
||||
* @param minFractionRendered The min fraction of the SurfaceControl that was resented
|
||||
* to the user to be considered inside the threshold.
|
||||
* @param stabilityRequirementMs The time in milliseconds required for the
|
||||
* {@link SurfaceControl} to be in the threshold.
|
||||
* @throws IllegalArgumentException If threshold values are invalid.
|
||||
*/
|
||||
public TrustedPresentationThresholds(
|
||||
@FloatRange(from = 0f, fromInclusive = false, to = 1f) float minAlpha,
|
||||
@FloatRange(from = 0f, fromInclusive = false, to = 1f) float minFractionRendered,
|
||||
@IntRange(from = 1) int stabilityRequirementMs) {
|
||||
mMinAlpha = minAlpha;
|
||||
mMinFractionRendered = minFractionRendered;
|
||||
mStabilityRequirementMs = stabilityRequirementMs;
|
||||
|
||||
checkValid();
|
||||
}
|
||||
|
||||
private void checkValid() {
|
||||
if (mMinAlpha <= 0 || mMinFractionRendered <= 0 || mStabilityRequirementMs < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"TrustedPresentationThresholds values are invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a TrustedPresentationCallback for a particular SurfaceControl so it can be notified
|
||||
* when the specified Threshold has been crossed.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract static class TrustedPresentationCallback {
|
||||
private final long mNativeObject;
|
||||
|
||||
private static final NativeAllocationRegistry sRegistry =
|
||||
NativeAllocationRegistry.createMalloced(
|
||||
TrustedPresentationCallback.class.getClassLoader(),
|
||||
getNativeTrustedPresentationCallbackFinalizer());
|
||||
|
||||
private final Runnable mFreeNativeResources;
|
||||
|
||||
private TrustedPresentationCallback() {
|
||||
mNativeObject = nativeCreateTpc(this);
|
||||
mFreeNativeResources = sRegistry.registerNativeAllocation(this, mNativeObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when the SurfaceControl that this TrustedPresentationCallback was registered for
|
||||
* enters or exits the threshold bounds.
|
||||
*
|
||||
* @param inTrustedPresentationState true when the SurfaceControl entered the
|
||||
* presentation state, false when it has left.
|
||||
*/
|
||||
public abstract void onTrustedPresentationChanged(boolean inTrustedPresentationState);
|
||||
}
|
||||
|
||||
/**
|
||||
* An atomic set of changes to a set of SurfaceControl.
|
||||
*/
|
||||
@@ -3776,6 +3856,106 @@ public final class SurfaceControl implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback to receive feedback about the presentation of a {@link SurfaceControl}.
|
||||
* When the {@link SurfaceControl} is presented according to the passed in
|
||||
* {@link TrustedPresentationThresholds}, it is said to "enter the state", and receives the
|
||||
* callback with {@code true}. When the conditions fall out of thresholds, it is then
|
||||
* said to leave the state.
|
||||
* <p>
|
||||
* There are a few simple thresholds:
|
||||
* <ul>
|
||||
* <li>minAlpha: Lower bound on computed alpha</li>
|
||||
* <li>minFractionRendered: Lower bounds on fraction of pixels that were rendered</li>
|
||||
* <li>stabilityThresholdMs: A time that alpha and fraction rendered must remain within
|
||||
* bounds before we can "enter the state" </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* The fraction of pixels rendered is a computation based on scale, crop
|
||||
* and occlusion. The calculation may be somewhat counterintuitive, so we
|
||||
* can work through an example. Imagine we have a SurfaceControl with a 100x100 buffer
|
||||
* which is occluded by (10x100) pixels on the left, and cropped by (100x10) pixels
|
||||
* on the top. Furthermore imagine this SurfaceControl is scaled by 0.9 in both dimensions.
|
||||
* (c=crop,o=occluded,b=both,x=none)
|
||||
*
|
||||
* <blockquote>
|
||||
* <table>
|
||||
* <caption></caption>
|
||||
* <tr><td>b</td><td>c</td><td>c</td><td>c</td></tr>
|
||||
* <tr><td>o</td><td>x</td><td>x</td><td>x</td></tr>
|
||||
* <tr><td>o</td><td>x</td><td>x</td><td>x</td></tr>
|
||||
* <tr><td>o</td><td>x</td><td>x</td><td>x</td></tr>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
*<p>
|
||||
* We first start by computing fr=xscale*yscale=0.9*0.9=0.81, indicating
|
||||
* that "81%" of the pixels were rendered. This corresponds to what was 100
|
||||
* pixels being displayed in 81 pixels. This is somewhat of an abuse of
|
||||
* language, as the information of merged pixels isn't totally lost, but
|
||||
* we err on the conservative side.
|
||||
* <p>
|
||||
* We then repeat a similar process for the crop and covered regions and
|
||||
* accumulate the results: fr = fr * (fractionNotCropped) * (fractionNotCovered)
|
||||
* So for this example we would get 0.9*0.9*0.9*0.9=0.65...
|
||||
* <p>
|
||||
* Notice that this is not completely accurate, as we have double counted
|
||||
* the region marked as b. However we only wanted a "lower bound" and so it
|
||||
* is ok to err in this direction. Selection of the threshold will ultimately
|
||||
* be somewhat arbitrary, and so there are some somewhat arbitrary decisions in
|
||||
* this API as well.
|
||||
* <p>
|
||||
* @param sc The {@link SurfaceControl} to set the
|
||||
* {@link TrustedPresentationCallback} on
|
||||
* @param thresholds The {@link TrustedPresentationThresholds} that will specify when the to
|
||||
* invoke the callback.
|
||||
* @param executor The {@link Executor} where the callback will be invoked on.
|
||||
* @param listener The {@link Consumer} that will receive the callbacks when entered or
|
||||
* exited the threshold.
|
||||
* @return This transaction
|
||||
* @see TrustedPresentationThresholds
|
||||
*/
|
||||
@NonNull
|
||||
public Transaction setTrustedPresentationCallback(@NonNull SurfaceControl sc,
|
||||
@NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor,
|
||||
@NonNull Consumer<Boolean> listener) {
|
||||
checkPreconditions(sc);
|
||||
TrustedPresentationCallback tpc = new TrustedPresentationCallback() {
|
||||
@Override
|
||||
public void onTrustedPresentationChanged(boolean inTrustedPresentationState) {
|
||||
executor.execute(
|
||||
() -> listener.accept(inTrustedPresentationState));
|
||||
}
|
||||
};
|
||||
|
||||
if (sc.mTrustedPresentationCallback != null) {
|
||||
sc.mTrustedPresentationCallback.mFreeNativeResources.run();
|
||||
}
|
||||
|
||||
nativeSetTrustedPresentationCallback(mNativeObject, sc.mNativeObject,
|
||||
tpc.mNativeObject, thresholds);
|
||||
sc.mTrustedPresentationCallback = tpc;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the {@link TrustedPresentationCallback} for a specific {@link SurfaceControl}
|
||||
*
|
||||
* @param sc The SurfaceControl that the {@link TrustedPresentationCallback} should be
|
||||
* cleared from
|
||||
* @return This transaction
|
||||
*/
|
||||
@NonNull
|
||||
public Transaction clearTrustedPresentationCallback(@NonNull SurfaceControl sc) {
|
||||
checkPreconditions(sc);
|
||||
nativeClearTrustedPresentationCallback(mNativeObject, sc.mNativeObject);
|
||||
if (sc.mTrustedPresentationCallback != null) {
|
||||
sc.mTrustedPresentationCallback.mFreeNativeResources.run();
|
||||
sc.mTrustedPresentationCallback = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the transaction to parcel, clearing the transaction as if it had been applied so
|
||||
* it can be used to store future transactions. It's the responsibility of the parcel
|
||||
|
||||
@@ -246,6 +246,17 @@ static struct {
|
||||
jmethodID invokeReleaseCallback;
|
||||
} gSurfaceControlClassInfo;
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
jfieldID mMinAlpha;
|
||||
jfieldID mMinFractionRendered;
|
||||
jfieldID mStabilityRequirementMs;
|
||||
} gTrustedPresentationThresholdsClassInfo;
|
||||
|
||||
static struct {
|
||||
jmethodID onTrustedPresentationChanged;
|
||||
} gTrustedPresentationCallbackClassInfo;
|
||||
|
||||
constexpr ui::Dataspace pickDataspaceFromColorMode(const ui::ColorMode colorMode) {
|
||||
switch (colorMode) {
|
||||
case ui::ColorMode::DISPLAY_P3:
|
||||
@@ -328,6 +339,47 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
class TrustedPresentationCallbackWrapper {
|
||||
public:
|
||||
explicit TrustedPresentationCallbackWrapper(JNIEnv* env, jobject trustedPresentationListener) {
|
||||
env->GetJavaVM(&mVm);
|
||||
mTrustedPresentationCallback = env->NewGlobalRef(trustedPresentationListener);
|
||||
LOG_ALWAYS_FATAL_IF(!mTrustedPresentationCallback, "Failed to make global ref");
|
||||
}
|
||||
|
||||
~TrustedPresentationCallbackWrapper() {
|
||||
getenv()->DeleteGlobalRef(mTrustedPresentationCallback);
|
||||
}
|
||||
|
||||
void onTrustedPresentationChanged(bool inTrustedPresentationState) {
|
||||
JNIEnv* env = getenv();
|
||||
env->CallVoidMethod(mTrustedPresentationCallback,
|
||||
gTrustedPresentationCallbackClassInfo.onTrustedPresentationChanged,
|
||||
inTrustedPresentationState);
|
||||
}
|
||||
|
||||
void addCallbackRef(const sp<SurfaceComposerClient::PresentationCallbackRAII>& callbackRef) {
|
||||
mCallbackRef = callbackRef;
|
||||
}
|
||||
|
||||
static void onTrustedPresentationChangedThunk(void* context, bool inTrustedPresentationState) {
|
||||
TrustedPresentationCallbackWrapper* listener =
|
||||
reinterpret_cast<TrustedPresentationCallbackWrapper*>(context);
|
||||
listener->onTrustedPresentationChanged(inTrustedPresentationState);
|
||||
}
|
||||
|
||||
private:
|
||||
jobject mTrustedPresentationCallback;
|
||||
JavaVM* mVm;
|
||||
sp<SurfaceComposerClient::PresentationCallbackRAII> mCallbackRef;
|
||||
|
||||
JNIEnv* getenv() {
|
||||
JNIEnv* env;
|
||||
mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
||||
return env;
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jlong nativeCreateTransaction(JNIEnv* env, jclass clazz) {
|
||||
@@ -1806,6 +1858,42 @@ static void nativeAddTransactionCommittedListener(JNIEnv* env, jclass clazz, jlo
|
||||
context);
|
||||
}
|
||||
|
||||
static void nativeSetTrustedPresentationCallback(JNIEnv* env, jclass clazz, jlong transactionObj,
|
||||
jlong nativeObject,
|
||||
jlong trustedPresentationCallbackObject,
|
||||
jobject trustedPresentationThresholds) {
|
||||
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
|
||||
auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
|
||||
|
||||
TrustedPresentationThresholds thresholds;
|
||||
thresholds.minAlpha = env->GetFloatField(trustedPresentationThresholds,
|
||||
gTrustedPresentationThresholdsClassInfo.mMinAlpha);
|
||||
thresholds.minFractionRendered =
|
||||
env->GetFloatField(trustedPresentationThresholds,
|
||||
gTrustedPresentationThresholdsClassInfo.mMinFractionRendered);
|
||||
thresholds.stabilityRequirementMs =
|
||||
env->GetIntField(trustedPresentationThresholds,
|
||||
gTrustedPresentationThresholdsClassInfo.mStabilityRequirementMs);
|
||||
|
||||
sp<SurfaceComposerClient::PresentationCallbackRAII> callbackRef;
|
||||
TrustedPresentationCallbackWrapper* wrapper =
|
||||
reinterpret_cast<TrustedPresentationCallbackWrapper*>(
|
||||
trustedPresentationCallbackObject);
|
||||
transaction->setTrustedPresentationCallback(ctrl,
|
||||
TrustedPresentationCallbackWrapper::
|
||||
onTrustedPresentationChangedThunk,
|
||||
thresholds, wrapper, callbackRef);
|
||||
wrapper->addCallbackRef(callbackRef);
|
||||
}
|
||||
|
||||
static void nativeClearTrustedPresentationCallback(JNIEnv* env, jclass clazz, jlong transactionObj,
|
||||
jlong nativeObject) {
|
||||
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
|
||||
auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
|
||||
|
||||
transaction->clearTrustedPresentationCallback(ctrl);
|
||||
}
|
||||
|
||||
class JankDataListenerWrapper : public JankDataListener {
|
||||
public:
|
||||
JankDataListenerWrapper(JNIEnv* env, jobject onJankDataListenerObject) {
|
||||
@@ -1919,6 +2007,21 @@ static jboolean nativeBootFinished(JNIEnv* env, jclass clazz) {
|
||||
return error == OK ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
jlong nativeCreateTpc(JNIEnv* env, jclass clazz, jobject trustedPresentationCallback) {
|
||||
return reinterpret_cast<jlong>(
|
||||
new TrustedPresentationCallbackWrapper(env, trustedPresentationCallback));
|
||||
}
|
||||
|
||||
void destroyNativeTpc(void* ptr) {
|
||||
TrustedPresentationCallbackWrapper* callback =
|
||||
reinterpret_cast<TrustedPresentationCallbackWrapper*>(ptr);
|
||||
delete callback;
|
||||
}
|
||||
|
||||
static jlong getNativeTrustedPresentationCallbackFinalizer(JNIEnv* env, jclass clazz) {
|
||||
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeTpc));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SurfaceControl* android_view_SurfaceControl_getNativeSurfaceControl(JNIEnv* env,
|
||||
@@ -2145,6 +2248,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
|
||||
(void*)nativeSetDropInputMode },
|
||||
{"nativeAddTransactionCommittedListener", "(JLandroid/view/SurfaceControl$TransactionCommittedListener;)V",
|
||||
(void*) nativeAddTransactionCommittedListener },
|
||||
{"nativeSetTrustedPresentationCallback", "(JJJLandroid/view/SurfaceControl$TrustedPresentationThresholds;)V",
|
||||
(void*) nativeSetTrustedPresentationCallback },
|
||||
{"nativeClearTrustedPresentationCallback", "(JJ)V",
|
||||
(void*) nativeClearTrustedPresentationCallback },
|
||||
{"nativeSanitize", "(J)V",
|
||||
(void*) nativeSanitize },
|
||||
{"nativeSetDestinationFrame", "(JJIIII)V",
|
||||
@@ -2155,6 +2262,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
|
||||
(void*)nativeGetDefaultApplyToken },
|
||||
{"nativeBootFinished", "()Z",
|
||||
(void*)nativeBootFinished },
|
||||
{"nativeCreateTpc", "(Landroid/view/SurfaceControl$TrustedPresentationCallback;)J",
|
||||
(void*)nativeCreateTpc},
|
||||
{"getNativeTrustedPresentationCallbackFinalizer", "()J", (void*)getNativeTrustedPresentationCallbackFinalizer },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
@@ -2381,6 +2491,23 @@ int register_android_view_SurfaceControl(JNIEnv* env)
|
||||
gTransactionClassInfo.mNativeObject =
|
||||
GetFieldIDOrDie(env, gTransactionClassInfo.clazz, "mNativeObject", "J");
|
||||
|
||||
jclass trustedPresentationThresholdsClazz =
|
||||
FindClassOrDie(env, "android/view/SurfaceControl$TrustedPresentationThresholds");
|
||||
gTrustedPresentationThresholdsClassInfo.clazz =
|
||||
MakeGlobalRefOrDie(env, trustedPresentationThresholdsClazz);
|
||||
gTrustedPresentationThresholdsClassInfo.mMinAlpha =
|
||||
GetFieldIDOrDie(env, trustedPresentationThresholdsClazz, "mMinAlpha", "F");
|
||||
gTrustedPresentationThresholdsClassInfo.mMinFractionRendered =
|
||||
GetFieldIDOrDie(env, trustedPresentationThresholdsClazz, "mMinFractionRendered", "F");
|
||||
gTrustedPresentationThresholdsClassInfo.mStabilityRequirementMs =
|
||||
GetFieldIDOrDie(env, trustedPresentationThresholdsClazz, "mStabilityRequirementMs",
|
||||
"I");
|
||||
|
||||
jclass trustedPresentationCallbackClazz =
|
||||
FindClassOrDie(env, "android/view/SurfaceControl$TrustedPresentationCallback");
|
||||
gTrustedPresentationCallbackClassInfo.onTrustedPresentationChanged =
|
||||
GetMethodIDOrDie(env, trustedPresentationCallbackClazz, "onTrustedPresentationChanged",
|
||||
"(Z)V");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user