Loading core/java/android/window/ScreenCapture.java +62 −18 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -281,6 +283,7 @@ public class ScreenCapture { mAllowProtected = builder.mAllowProtected; mUid = builder.mUid; mGrayscale = builder.mGrayscale; mExcludeLayers = builder.mExcludeLayers; } private CaptureArgs(Parcel in) { Loading @@ -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; } /** Loading @@ -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 Loading Loading @@ -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 */ Loading @@ -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 = Loading Loading @@ -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; } } /** Loading @@ -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; /** Loading @@ -575,6 +626,7 @@ public class ScreenCapture { setAllowProtected(args.mAllowProtected); setUid(args.mUid); setGrayscale(args.mGrayscale); setExcludeLayers(args.mExcludeLayers); } public Builder(SurfaceControl layer) { Loading @@ -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. Loading core/jni/android_window_ScreenCapture.cpp +22 −20 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ static struct { jfieldID allowProtected; jfieldID uid; jfieldID grayscale; jmethodID getNativeExcludeLayers; } gCaptureArgsClassInfo; static struct { Loading @@ -56,7 +57,6 @@ static struct { static struct { jfieldID layer; jfieldID excludeLayers; jfieldID childrenOnly; } gLayerCaptureArgsClassInfo; Loading Loading @@ -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, Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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 = Loading @@ -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"); Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +16 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"); } Loading services/core/java/com/android/server/wm/WindowManagerService.java +8 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
core/java/android/window/ScreenCapture.java +62 −18 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -281,6 +283,7 @@ public class ScreenCapture { mAllowProtected = builder.mAllowProtected; mUid = builder.mUid; mGrayscale = builder.mGrayscale; mExcludeLayers = builder.mExcludeLayers; } private CaptureArgs(Parcel in) { Loading @@ -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; } /** Loading @@ -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 Loading Loading @@ -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 */ Loading @@ -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 = Loading Loading @@ -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; } } /** Loading @@ -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; /** Loading @@ -575,6 +626,7 @@ public class ScreenCapture { setAllowProtected(args.mAllowProtected); setUid(args.mUid); setGrayscale(args.mGrayscale); setExcludeLayers(args.mExcludeLayers); } public Builder(SurfaceControl layer) { Loading @@ -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. Loading
core/jni/android_window_ScreenCapture.cpp +22 −20 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ static struct { jfieldID allowProtected; jfieldID uid; jfieldID grayscale; jmethodID getNativeExcludeLayers; } gCaptureArgsClassInfo; static struct { Loading @@ -56,7 +57,6 @@ static struct { static struct { jfieldID layer; jfieldID excludeLayers; jfieldID childrenOnly; } gLayerCaptureArgsClassInfo; Loading Loading @@ -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, Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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 = Loading @@ -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"); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +16 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"); } Loading
services/core/java/com/android/server/wm/WindowManagerService.java +8 −1 Original line number Diff line number Diff line Loading @@ -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 Loading