private boolean captureScreenshotTextureAndSetViewport() { if (!attachEglContext()) { return false; } try { if (!mTexNamesGenerated) { GLES10.glGenTextures(1, mTexNames, 0); if (checkGlErrors("glGenTextures")) { return false; } mTexNamesGenerated = true; } final SurfaceTexture st = new SurfaceTexture(mTexNames[0]); final Surface s = new Surface(st); try { SurfaceControl.screenshot( SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), s); } finally { s.release(); } st.updateTexImage(); st.getTransformMatrix(mTexMatrix); // Set up texture coordinates for a quad. // We might need to change this if the texture ends up being // a different size from the display for some reason. mTexCoordBuffer.put(0, 0f); mTexCoordBuffer.put(1, 0f); mTexCoordBuffer.put(2, 0f); mTexCoordBuffer.put(3, 1f); mTexCoordBuffer.put(4, 1f); mTexCoordBuffer.put(5, 1f); mTexCoordBuffer.put(6, 1f); mTexCoordBuffer.put(7, 0f); // Set up our viewport. GLES10.glViewport(0, 0, mDisplayWidth, mDisplayHeight); GLES10.glMatrixMode(GLES10.GL_PROJECTION); GLES10.glLoadIdentity(); GLES10.glOrthof(0, mDisplayWidth, 0, mDisplayHeight, 0, 1); GLES10.glMatrixMode(GLES10.GL_MODELVIEW); GLES10.glLoadIdentity(); GLES10.glMatrixMode(GLES10.GL_TEXTURE); GLES10.glLoadIdentity(); GLES10.glLoadMatrixf(mTexMatrix, 0); } finally { detachEglContext(); } return true; }
@Override public void onDisplayTransaction() { synchronized (this) { if (mSurfaceControl == null) { return; } DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY); switch ((displayInfo.rotation + mHWRotation) % 4) { case Surface.ROTATION_0: mSurfaceControl.setPosition(0, 0); mSurfaceControl.setMatrix(1, 0, 0, 1); break; case Surface.ROTATION_90: mSurfaceControl.setPosition(0, displayInfo.logicalHeight); mSurfaceControl.setMatrix(0, -1, 1, 0); break; case Surface.ROTATION_180: mSurfaceControl.setPosition(displayInfo.logicalWidth, displayInfo.logicalHeight); mSurfaceControl.setMatrix(-1, 0, 0, -1); break; case Surface.ROTATION_270: mSurfaceControl.setPosition(displayInfo.logicalWidth, 0); mSurfaceControl.setMatrix(0, 1, -1, 0); break; } } }
private boolean showSurface(float alpha) { if (!mSurfaceVisible || mSurfaceAlpha != alpha) { SurfaceControl.openTransaction(); try { mSurfaceControl.setLayer(ELECTRON_BEAM_LAYER); mSurfaceControl.setAlpha(alpha); mSurfaceControl.show(); } finally { SurfaceControl.closeTransaction(); } mSurfaceVisible = true; mSurfaceAlpha = alpha; } return true; }
public void updateSize() { synchronized (mWindowManagerService.mWindowMap) { mWindowManager.getDefaultDisplay().getRealSize(mTempPoint); mSurfaceControl.setSize(mTempPoint.x, mTempPoint.y); invalidate(mDirtyRect); } }
private void destroySurface() { if (mSurfaceControl != null) { mSurfaceLayout.dispose(); mSurfaceLayout = null; SurfaceControl.openTransaction(); try { mSurfaceControl.destroy(); mSurface.release(); } finally { SurfaceControl.closeTransaction(); } mSurfaceControl = null; mSurfaceVisible = false; mSurfaceAlpha = 0f; } }
/** * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but includes all Surfaces * in the screenshot. * * @param width The desired width of the returned bitmap; the raw screen will be scaled down to * this size. * @param height The desired height of the returned bitmap; the raw screen will be scaled down to * this size. * @return Returns a Bitmap containing the screen contents, or null if an error occurs. Make sure * to call Bitmap.recycle() as soon as possible, once its content is not needed anymore. */ public static Bitmap screenshot(int width, int height) { // TODO: should take the display as a parameter IBinder displayToken = SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); return nativeScreenshot( displayToken, new Rect(), width, height, 0, 0, true, false, Surface.ROTATION_0); }
public void setBlurMaskSurface(SurfaceControl maskSurface) { checkNotReleased(); if (maskSurface != null) { maskSurface.checkNotReleased(); } nativeSetBlurMaskSurface(mNativeObject, maskSurface == null ? 0 : maskSurface.mNativeObject); }
/** NOTE: This has to be called within a surface transaction. */ public void drawIfNeeded() { synchronized (mWindowManagerService.mWindowMap) { if (!mInvalidated) { return; } mInvalidated = false; Canvas canvas = null; try { // Empty dirty rectangle means unspecified. if (mDirtyRect.isEmpty()) { mBounds.getBounds(mDirtyRect); } mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth); canvas = mSurface.lockCanvas(mDirtyRect); if (DEBUG_VIEWPORT_WINDOW) { Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect); } } catch (IllegalArgumentException iae) { /* ignore */ } catch (Surface.OutOfResourcesException oore) { /* ignore */ } if (canvas == null) { return; } if (DEBUG_VIEWPORT_WINDOW) { Slog.i(LOG_TAG, "Bounds: " + mBounds); } canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR); mPaint.setAlpha(mAlpha); Path path = mBounds.getBoundaryPath(); canvas.drawPath(path, mPaint); mSurface.unlockCanvasAndPost(canvas); if (mAlpha > 0) { mSurfaceControl.show(); } else { mSurfaceControl.hide(); } } }
public ViewportWindow(Context context) { SurfaceControl surfaceControl = null; try { mWindowManager.getDefaultDisplay().getRealSize(mTempPoint); surfaceControl = new SurfaceControl( mWindowManagerService.mFxSession, SURFACE_TITLE, mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); } catch (OutOfResourcesException oore) { /* ignore */ } mSurfaceControl = surfaceControl; mSurfaceControl.setLayerStack(mWindowManager.getDefaultDisplay().getLayerStack()); mSurfaceControl.setLayer( mWindowManagerService.mPolicy.windowTypeToLayerLw( WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY) * WindowManagerService.TYPE_LAYER_MULTIPLIER); mSurfaceControl.setPosition(0, 0); mSurface.copyFrom(mSurfaceControl); TypedValue typedValue = new TypedValue(); context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight, typedValue, true); final int borderColor = context.getResources().getColor(typedValue.resourceId); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mBorderWidth); mPaint.setColor(borderColor); Interpolator interpolator = new DecelerateInterpolator(2.5f); final long longAnimationDuration = context.getResources().getInteger(com.android.internal.R.integer.config_longAnimTime); mShowHideFrameAnimator = ObjectAnimator.ofInt(this, PROPERTY_NAME_ALPHA, MIN_ALPHA, MAX_ALPHA); mShowHideFrameAnimator.setInterpolator(interpolator); mShowHideFrameAnimator.setDuration(longAnimationDuration); mInvalidated = true; }
private boolean createSurface() { if (mSurfaceSession == null) { mSurfaceSession = new SurfaceSession(); } SurfaceControl.openTransaction(); try { if (mSurfaceControl == null) { try { int flags; if (mMode == MODE_FADE) { flags = SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN; } else { flags = SurfaceControl.OPAQUE | SurfaceControl.HIDDEN; } mSurfaceControl = new SurfaceControl( mSurfaceSession, "ElectronBeam", mDisplayWidth, mDisplayHeight, PixelFormat.OPAQUE, flags); } catch (OutOfResourcesException ex) { Slog.e(TAG, "Unable to create surface.", ex); return false; } } mSurfaceControl.setLayerStack(mDisplayLayerStack); mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight); mSurface = new Surface(); mSurface.copyFrom(mSurfaceControl); mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl, mHWRotation); mSurfaceLayout.onDisplayTransaction(); } finally { SurfaceControl.closeTransaction(); } return true; }
@Override public void clearWindowAnimationFrameStats() { synchronized (mLock) { throwIfCalledByNotTrustedUidLocked(); throwIfShutdownLocked(); throwIfNotConnectedLocked(); } final long identity = Binder.clearCallingIdentity(); try { SurfaceControl.clearAnimationFrameStats(); } finally { Binder.restoreCallingIdentity(identity); } }
@Override public Bitmap takeScreenshot(int width, int height) { synchronized (mLock) { throwIfCalledByNotTrustedUidLocked(); throwIfShutdownLocked(); throwIfNotConnectedLocked(); } final long identity = Binder.clearCallingIdentity(); try { return SurfaceControl.screenshot(width, height); } finally { Binder.restoreCallingIdentity(identity); } }
@Override public WindowAnimationFrameStats getWindowAnimationFrameStats() { synchronized (mLock) { throwIfCalledByNotTrustedUidLocked(); throwIfShutdownLocked(); throwIfNotConnectedLocked(); } final long identity = Binder.clearCallingIdentity(); try { WindowAnimationFrameStats stats = new WindowAnimationFrameStats(); SurfaceControl.getAnimationFrameStats(stats); return stats; } finally { Binder.restoreCallingIdentity(identity); } }
private static Bitmap surfaceControlScreenshot(int width, int height) throws Exception { // if (mSurfaceControlScreenshotMethod == null) { // Class<?> clazz = Class.forName(SURFACE_CONTROL_CLASS_NAME); // if (clazz != null) // mSurfaceControlScreenshotMethod = clazz.getDeclaredMethod("screenshot", Integer.TYPE, // Integer.TYPE); // } // Object object = mSurfaceControlScreenshotMethod.invoke(null, width, height); // if (object != null) { // return (Bitmap) object; // } // return null; return SurfaceControl.screenshot(width, height); }
/** * Copy the current screen contents into a bitmap and return it. * * <p>CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use * unless absolutely necessary; prefer the versions that use a {@link Surface} instead, such as * {@link SurfaceControl#screenshot(IBinder, Surface)}. * * @param sourceCrop The portion of the screen to capture into the Bitmap; caller may pass in 'new * Rect()' if no cropping is desired. * @param width The desired width of the returned bitmap; the raw screen will be scaled down to * this size. * @param height The desired height of the returned bitmap; the raw screen will be scaled down to * this size. * @param minLayer The lowest (bottom-most Z order) surface layer to include in the screenshot. * @param maxLayer The highest (top-most Z order) surface layer to include in the screenshot. * @param useIdentityTransform Replace whatever transformation (rotation, scaling, translation) * the surface layers are currently using with the identity transformation while taking the * screenshot. * @param rotation Apply a custom clockwise rotation to the screenshot, i.e. * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take screenshots in its native * portrait orientation by default, so this is useful for returning screenshots that are * independent of device orientation. * @return Returns a Bitmap containing the screen contents, or null if an error occurs. Make sure * to call Bitmap.recycle() as soon as possible, once its content is not needed anymore. */ public static Bitmap screenshot( Rect sourceCrop, int width, int height, int minLayer, int maxLayer, boolean useIdentityTransform, int rotation) { // TODO: should take the display as a parameter IBinder displayToken = SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN); return nativeScreenshot( displayToken, sourceCrop, width, height, minLayer, maxLayer, false, useIdentityTransform, rotation); }
public void releaseSurface() { mSurfaceControl.release(); mSurface.release(); }