Merge "Move exclude layer to CaptureArgs." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8f23f6bb53
@@ -272,6 +272,8 @@ public class ScreenCapture {
|
||||
public final long mUid;
|
||||
public final boolean mGrayscale;
|
||||
|
||||
final SurfaceControl[] mExcludeLayers;
|
||||
|
||||
private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) {
|
||||
mPixelFormat = builder.mPixelFormat;
|
||||
mSourceCrop.set(builder.mSourceCrop);
|
||||
@@ -281,6 +283,7 @@ public class ScreenCapture {
|
||||
mAllowProtected = builder.mAllowProtected;
|
||||
mUid = builder.mUid;
|
||||
mGrayscale = builder.mGrayscale;
|
||||
mExcludeLayers = builder.mExcludeLayers;
|
||||
}
|
||||
|
||||
private CaptureArgs(Parcel in) {
|
||||
@@ -292,6 +295,46 @@ public class ScreenCapture {
|
||||
mAllowProtected = in.readBoolean();
|
||||
mUid = in.readLong();
|
||||
mGrayscale = in.readBoolean();
|
||||
|
||||
int excludeLayersLength = in.readInt();
|
||||
if (excludeLayersLength > 0) {
|
||||
mExcludeLayers = new SurfaceControl[excludeLayersLength];
|
||||
for (int index = 0; index < excludeLayersLength; index++) {
|
||||
mExcludeLayers[index] = SurfaceControl.CREATOR.createFromParcel(in);
|
||||
}
|
||||
} else {
|
||||
mExcludeLayers = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Release any layers if set using {@link Builder#setExcludeLayers(SurfaceControl[])}. */
|
||||
public void release() {
|
||||
if (mExcludeLayers.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (SurfaceControl surfaceControl : mExcludeLayers) {
|
||||
if (surfaceControl != null) {
|
||||
surfaceControl.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of {@link SurfaceControl#mNativeObject} corresponding to
|
||||
* {@link #mExcludeLayers}. Used only in native code.
|
||||
*/
|
||||
private long[] getNativeExcludeLayers() {
|
||||
if (mExcludeLayers == null || mExcludeLayers.length == 0) {
|
||||
return new long[0];
|
||||
}
|
||||
|
||||
long[] nativeExcludeLayers = new long[mExcludeLayers.length];
|
||||
for (int index = 0; index < mExcludeLayers.length; index++) {
|
||||
nativeExcludeLayers[index] = mExcludeLayers[index].mNativeObject;
|
||||
}
|
||||
|
||||
return nativeExcludeLayers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,6 +351,7 @@ public class ScreenCapture {
|
||||
private boolean mAllowProtected;
|
||||
private long mUid = -1;
|
||||
private boolean mGrayscale;
|
||||
private SurfaceControl[] mExcludeLayers;
|
||||
|
||||
/**
|
||||
* Construct a new {@link CaptureArgs} with the set parameters. The builder remains
|
||||
@@ -396,6 +440,14 @@ public class ScreenCapture {
|
||||
return getThis();
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of {@link SurfaceControl} layer handles to exclude.
|
||||
*/
|
||||
public T setExcludeLayers(@Nullable SurfaceControl[] excludeLayers) {
|
||||
mExcludeLayers = excludeLayers;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Each sub class should return itself to allow the builder to chain properly
|
||||
*/
|
||||
@@ -419,6 +471,15 @@ public class ScreenCapture {
|
||||
dest.writeBoolean(mAllowProtected);
|
||||
dest.writeLong(mUid);
|
||||
dest.writeBoolean(mGrayscale);
|
||||
|
||||
if (mExcludeLayers != null) {
|
||||
dest.writeInt(mExcludeLayers.length);
|
||||
for (SurfaceControl excludeLayer : mExcludeLayers) {
|
||||
excludeLayer.writeToParcel(dest, flags);
|
||||
}
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<CaptureArgs> CREATOR =
|
||||
@@ -529,21 +590,12 @@ public class ScreenCapture {
|
||||
*/
|
||||
public static class LayerCaptureArgs extends CaptureArgs {
|
||||
private final long mNativeLayer;
|
||||
private final long[] mNativeExcludeLayers;
|
||||
private final boolean mChildrenOnly;
|
||||
|
||||
private LayerCaptureArgs(Builder builder) {
|
||||
super(builder);
|
||||
mChildrenOnly = builder.mChildrenOnly;
|
||||
mNativeLayer = builder.mLayer.mNativeObject;
|
||||
if (builder.mExcludeLayers != null) {
|
||||
mNativeExcludeLayers = new long[builder.mExcludeLayers.length];
|
||||
for (int i = 0; i < builder.mExcludeLayers.length; i++) {
|
||||
mNativeExcludeLayers[i] = builder.mExcludeLayers[i].mNativeObject;
|
||||
}
|
||||
} else {
|
||||
mNativeExcludeLayers = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -551,7 +603,6 @@ public class ScreenCapture {
|
||||
*/
|
||||
public static class Builder extends CaptureArgs.Builder<Builder> {
|
||||
private SurfaceControl mLayer;
|
||||
private SurfaceControl[] mExcludeLayers;
|
||||
private boolean mChildrenOnly = true;
|
||||
|
||||
/**
|
||||
@@ -575,6 +626,7 @@ public class ScreenCapture {
|
||||
setAllowProtected(args.mAllowProtected);
|
||||
setUid(args.mUid);
|
||||
setGrayscale(args.mGrayscale);
|
||||
setExcludeLayers(args.mExcludeLayers);
|
||||
}
|
||||
|
||||
public Builder(SurfaceControl layer) {
|
||||
@@ -589,14 +641,6 @@ public class ScreenCapture {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of layer handles to exclude.
|
||||
*/
|
||||
public Builder setExcludeLayers(@Nullable SurfaceControl[] excludeLayers) {
|
||||
mExcludeLayers = excludeLayers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to include the layer itself in the screenshot or just the children and their
|
||||
* descendants.
|
||||
|
||||
@@ -45,6 +45,7 @@ static struct {
|
||||
jfieldID allowProtected;
|
||||
jfieldID uid;
|
||||
jfieldID grayscale;
|
||||
jmethodID getNativeExcludeLayers;
|
||||
} gCaptureArgsClassInfo;
|
||||
|
||||
static struct {
|
||||
@@ -56,7 +57,6 @@ static struct {
|
||||
|
||||
static struct {
|
||||
jfieldID layer;
|
||||
jfieldID excludeLayers;
|
||||
jfieldID childrenOnly;
|
||||
} gLayerCaptureArgsClassInfo;
|
||||
|
||||
@@ -168,6 +168,23 @@ static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs&
|
||||
captureArgs.uid = env->GetLongField(captureArgsObject, gCaptureArgsClassInfo.uid);
|
||||
captureArgs.grayscale =
|
||||
env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.grayscale);
|
||||
|
||||
jlongArray excludeObjectArray = reinterpret_cast<jlongArray>(
|
||||
env->CallObjectMethod(captureArgsObject, gCaptureArgsClassInfo.getNativeExcludeLayers));
|
||||
if (excludeObjectArray != nullptr) {
|
||||
ScopedLongArrayRO excludeArray(env, excludeObjectArray);
|
||||
const jsize len = excludeArray.size();
|
||||
captureArgs.excludeHandles.reserve(len);
|
||||
|
||||
for (jsize i = 0; i < len; i++) {
|
||||
auto excludeObject = reinterpret_cast<SurfaceControl*>(excludeArray[i]);
|
||||
if (excludeObject == nullptr) {
|
||||
jniThrowNullPointerException(env, "Exclude layer is null");
|
||||
return;
|
||||
}
|
||||
captureArgs.excludeHandles.emplace(excludeObject->getHandle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
|
||||
@@ -207,6 +224,7 @@ static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureA
|
||||
jlong screenCaptureListenerObject) {
|
||||
LayerCaptureArgs captureArgs;
|
||||
getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
|
||||
|
||||
SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
|
||||
env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer));
|
||||
if (layer == nullptr) {
|
||||
@@ -217,23 +235,6 @@ static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureA
|
||||
captureArgs.childrenOnly =
|
||||
env->GetBooleanField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.childrenOnly);
|
||||
|
||||
jlongArray excludeObjectArray = reinterpret_cast<jlongArray>(
|
||||
env->GetObjectField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.excludeLayers));
|
||||
if (excludeObjectArray != nullptr) {
|
||||
ScopedLongArrayRO excludeArray(env, excludeObjectArray);
|
||||
const jsize len = excludeArray.size();
|
||||
captureArgs.excludeHandles.reserve(len);
|
||||
|
||||
for (jsize i = 0; i < len; i++) {
|
||||
auto excludeObject = reinterpret_cast<SurfaceControl*>(excludeArray[i]);
|
||||
if (excludeObject == nullptr) {
|
||||
jniThrowNullPointerException(env, "Exclude layer is null");
|
||||
return BAD_VALUE;
|
||||
}
|
||||
captureArgs.excludeHandles.emplace(excludeObject->getHandle());
|
||||
}
|
||||
}
|
||||
|
||||
sp<gui::IScreenCaptureListener> captureListener =
|
||||
reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
|
||||
return ScreenshotClient::captureLayers(captureArgs, captureListener);
|
||||
@@ -318,6 +319,9 @@ int register_android_window_ScreenCapture(JNIEnv* env) {
|
||||
gCaptureArgsClassInfo.uid = GetFieldIDOrDie(env, captureArgsClazz, "mUid", "J");
|
||||
gCaptureArgsClassInfo.grayscale = GetFieldIDOrDie(env, captureArgsClazz, "mGrayscale", "Z");
|
||||
|
||||
gCaptureArgsClassInfo.getNativeExcludeLayers =
|
||||
GetMethodIDOrDie(env, captureArgsClazz, "getNativeExcludeLayers", "()[J");
|
||||
|
||||
jclass displayCaptureArgsClazz =
|
||||
FindClassOrDie(env, "android/window/ScreenCapture$DisplayCaptureArgs");
|
||||
gDisplayCaptureArgsClassInfo.displayToken =
|
||||
@@ -333,8 +337,6 @@ int register_android_window_ScreenCapture(JNIEnv* env) {
|
||||
FindClassOrDie(env, "android/window/ScreenCapture$LayerCaptureArgs");
|
||||
gLayerCaptureArgsClassInfo.layer =
|
||||
GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeLayer", "J");
|
||||
gLayerCaptureArgsClassInfo.excludeLayers =
|
||||
GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeExcludeLayers", "[J");
|
||||
gLayerCaptureArgsClassInfo.childrenOnly =
|
||||
GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");
|
||||
|
||||
|
||||
@@ -74,8 +74,10 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseArray;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewRootImpl;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.window.ScreenCapture;
|
||||
@@ -1186,13 +1188,24 @@ public class BubbleController implements ConfigurationChangeListener,
|
||||
/**
|
||||
* Performs a screenshot that may exclude the bubble layer, if one is present. The screenshot
|
||||
* can be access via the supplied {@link ScreenshotSync#get()} asynchronously.
|
||||
*
|
||||
* TODO(b/267324693): Implement the exclude layer functionality in screenshot.
|
||||
*/
|
||||
public void getScreenshotExcludingBubble(int displayId,
|
||||
Pair<ScreenCaptureListener, ScreenshotSync> screenCaptureListener) {
|
||||
try {
|
||||
mWmService.captureDisplay(displayId, null, screenCaptureListener.first);
|
||||
ScreenCapture.CaptureArgs args = null;
|
||||
if (mStackView != null) {
|
||||
ViewRootImpl viewRoot = mStackView.getViewRootImpl();
|
||||
if (viewRoot != null) {
|
||||
SurfaceControl bubbleLayer = viewRoot.getSurfaceControl();
|
||||
if (bubbleLayer != null) {
|
||||
args = new ScreenCapture.CaptureArgs.Builder<>()
|
||||
.setExcludeLayers(new SurfaceControl[] {bubbleLayer})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWmService.captureDisplay(displayId, args, screenCaptureListener.first);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to capture screenshot");
|
||||
}
|
||||
|
||||
@@ -9315,7 +9315,14 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
|
||||
}
|
||||
|
||||
ScreenCapture.captureLayers(getCaptureArgs(displayId, captureArgs), listener);
|
||||
ScreenCapture.LayerCaptureArgs layerCaptureArgs = getCaptureArgs(displayId, captureArgs);
|
||||
ScreenCapture.captureLayers(layerCaptureArgs, listener);
|
||||
|
||||
if (Binder.getCallingUid() != SYSTEM_UID) {
|
||||
// Release the SurfaceControl objects only if the caller is not in system server as no
|
||||
// parcelling occurs in this case.
|
||||
layerCaptureArgs.release();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
Reference in New Issue
Block a user