Loading services/java/com/android/server/wm/WindowManagerService.java +181 −103 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Point; Loading Loading @@ -282,6 +283,8 @@ public class WindowManagerService extends IWindowManager.Stub private static final String SYSTEM_SECURE = "ro.secure"; private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; private static final int MAX_SCREENSHOT_RETRIES = 3; final private KeyguardDisableHandler mKeyguardDisableHandler; private final boolean mHeadless; Loading Loading @@ -5277,18 +5280,36 @@ public class WindowManagerService extends IWindowManager.Stub throw new SecurityException("Requires READ_FRAME_BUFFER permission"); } Bitmap rawss; Bitmap rawss = null; int maxLayer = 0; final Rect frame = new Rect(); float scale; float scale = 0; int dw, dh; int rot; int rot = Surface.ROTATION_0; synchronized(mWindowMap) { long ident = Binder.clearCallingIdentity(); boolean screenshotReady; int minLayer; if (appToken == null) { screenshotReady = true; minLayer = 0; } else { screenshotReady = false; minLayer = Integer.MAX_VALUE; } int retryCount = 0; WindowState appWin = null; do { if (retryCount++ > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { } } synchronized(mWindowMap) { final DisplayContent displayContent = getDisplayContentLocked(displayId); if (displayContent == null) { return null; Loading @@ -5308,6 +5329,7 @@ public class WindowManagerService extends IWindowManager.Stub // Figure out the part of the screen that is actually the app. boolean including = false; appWin = null; final WindowList windows = displayContent.getWindowList(); for (int i = windows.size() - 1; i >= 0; i--) { WindowState ws = windows.get(i); Loading @@ -5330,15 +5352,18 @@ public class WindowManagerService extends IWindowManager.Stub if (ws.mAppToken == null || ws.mAppToken.token != appToken) { continue; } appWin = ws; } } // We keep on including windows until we go past a full-screen // window. including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); boolean fullscreen = ws.isFullscreen(dw, dh); including = !ws.mIsImWindow && !fullscreen; if (maxLayer < ws.mWinAnimator.mSurfaceLayer) { maxLayer = ws.mWinAnimator.mSurfaceLayer; final WindowStateAnimator winAnim = ws.mWinAnimator; if (maxLayer < winAnim.mSurfaceLayer) { maxLayer = winAnim.mSurfaceLayer; } // Don't include wallpaper in bounds calculation Loading @@ -5351,13 +5376,41 @@ public class WindowManagerService extends IWindowManager.Stub int bottom = wf.bottom - cr.bottom; frame.union(left, top, right, bottom); } if (ws.mAppToken != null && ws.mAppToken.token == appToken) { if (minLayer > ws.mWinAnimator.mSurfaceLayer) { minLayer = ws.mWinAnimator.mSurfaceLayer; } if (ws.isDisplayedLw()) { screenshotReady = true; } if (fullscreen) { // No point in continuing down through windows. break; } } } if (appToken != null && appWin == null) { // Can't find a window to snapshot. if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: Couldn't find a surface matching " + appToken); return null; } if (!screenshotReady) { // Delay and hope that window gets drawn. if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); continue; } Binder.restoreCallingIdentity(ident); // Constrain frame to the screen size. frame.intersect(0, 0, dw, dh); if (frame.isEmpty() || maxLayer == 0) { if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken + ": returning null frame=" + frame.toShortString() + " maxLayer=" + maxLayer); return null; } Loading Loading @@ -5396,7 +5449,8 @@ public class WindowManagerService extends IWindowManager.Stub rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; } if (DEBUG_SCREENSHOT) { Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer); Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " + maxLayer + " appToken=" + appToken); for (int i = 0; i < windows.size(); i++) { WindowState win = windows.get(i); Slog.i(TAG, win + ": " + win.mLayer Loading @@ -5404,7 +5458,13 @@ public class WindowManagerService extends IWindowManager.Stub + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); } } rawss = SurfaceControl.screenshot(dw, dh, 0, maxLayer); rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer); } } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); if (DEBUG_SCREENSHOT && retryCount > MAX_SCREENSHOT_RETRIES) { Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken + " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); } if (rawss == null) { Loading @@ -5421,6 +5481,23 @@ public class WindowManagerService extends IWindowManager.Stub canvas.drawBitmap(rawss, matrix, null); canvas.setBitmap(null); if (DEBUG_SCREENSHOT) { // TEST IF IT's ALL BLACK int[] buffer = new int[bm.getWidth() * bm.getHeight()]; bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); boolean allBlack = true; for (int i = 0; i < buffer.length; i++) { if (buffer[i] != Color.BLACK) { allBlack = false; break; } } if (allBlack) { Slog.i(TAG, "Screenshot " + appWin + " was all black! mSurfaceLayer=" + (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null")); } } rawss.recycle(); return bm; } Loading Loading @@ -7408,6 +7485,7 @@ public class WindowManagerService extends IWindowManager.Stub performLayoutAndPlaceSurfacesLocked(); } @Override public void setOverscan(int displayId, int left, int top, int right, int bottom) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.WRITE_SECURE_SETTINGS) != Loading Loading
services/java/com/android/server/wm/WindowManagerService.java +181 −103 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Point; Loading Loading @@ -282,6 +283,8 @@ public class WindowManagerService extends IWindowManager.Stub private static final String SYSTEM_SECURE = "ro.secure"; private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; private static final int MAX_SCREENSHOT_RETRIES = 3; final private KeyguardDisableHandler mKeyguardDisableHandler; private final boolean mHeadless; Loading Loading @@ -5277,18 +5280,36 @@ public class WindowManagerService extends IWindowManager.Stub throw new SecurityException("Requires READ_FRAME_BUFFER permission"); } Bitmap rawss; Bitmap rawss = null; int maxLayer = 0; final Rect frame = new Rect(); float scale; float scale = 0; int dw, dh; int rot; int rot = Surface.ROTATION_0; synchronized(mWindowMap) { long ident = Binder.clearCallingIdentity(); boolean screenshotReady; int minLayer; if (appToken == null) { screenshotReady = true; minLayer = 0; } else { screenshotReady = false; minLayer = Integer.MAX_VALUE; } int retryCount = 0; WindowState appWin = null; do { if (retryCount++ > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { } } synchronized(mWindowMap) { final DisplayContent displayContent = getDisplayContentLocked(displayId); if (displayContent == null) { return null; Loading @@ -5308,6 +5329,7 @@ public class WindowManagerService extends IWindowManager.Stub // Figure out the part of the screen that is actually the app. boolean including = false; appWin = null; final WindowList windows = displayContent.getWindowList(); for (int i = windows.size() - 1; i >= 0; i--) { WindowState ws = windows.get(i); Loading @@ -5330,15 +5352,18 @@ public class WindowManagerService extends IWindowManager.Stub if (ws.mAppToken == null || ws.mAppToken.token != appToken) { continue; } appWin = ws; } } // We keep on including windows until we go past a full-screen // window. including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); boolean fullscreen = ws.isFullscreen(dw, dh); including = !ws.mIsImWindow && !fullscreen; if (maxLayer < ws.mWinAnimator.mSurfaceLayer) { maxLayer = ws.mWinAnimator.mSurfaceLayer; final WindowStateAnimator winAnim = ws.mWinAnimator; if (maxLayer < winAnim.mSurfaceLayer) { maxLayer = winAnim.mSurfaceLayer; } // Don't include wallpaper in bounds calculation Loading @@ -5351,13 +5376,41 @@ public class WindowManagerService extends IWindowManager.Stub int bottom = wf.bottom - cr.bottom; frame.union(left, top, right, bottom); } if (ws.mAppToken != null && ws.mAppToken.token == appToken) { if (minLayer > ws.mWinAnimator.mSurfaceLayer) { minLayer = ws.mWinAnimator.mSurfaceLayer; } if (ws.isDisplayedLw()) { screenshotReady = true; } if (fullscreen) { // No point in continuing down through windows. break; } } } if (appToken != null && appWin == null) { // Can't find a window to snapshot. if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: Couldn't find a surface matching " + appToken); return null; } if (!screenshotReady) { // Delay and hope that window gets drawn. if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState); continue; } Binder.restoreCallingIdentity(ident); // Constrain frame to the screen size. frame.intersect(0, 0, dw, dh); if (frame.isEmpty() || maxLayer == 0) { if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken + ": returning null frame=" + frame.toShortString() + " maxLayer=" + maxLayer); return null; } Loading Loading @@ -5396,7 +5449,8 @@ public class WindowManagerService extends IWindowManager.Stub rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; } if (DEBUG_SCREENSHOT) { Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer); Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to " + maxLayer + " appToken=" + appToken); for (int i = 0; i < windows.size(); i++) { WindowState win = windows.get(i); Slog.i(TAG, win + ": " + win.mLayer Loading @@ -5404,7 +5458,13 @@ public class WindowManagerService extends IWindowManager.Stub + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer); } } rawss = SurfaceControl.screenshot(dw, dh, 0, maxLayer); rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer); } } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES); if (DEBUG_SCREENSHOT && retryCount > MAX_SCREENSHOT_RETRIES) { Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken + " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState))); } if (rawss == null) { Loading @@ -5421,6 +5481,23 @@ public class WindowManagerService extends IWindowManager.Stub canvas.drawBitmap(rawss, matrix, null); canvas.setBitmap(null); if (DEBUG_SCREENSHOT) { // TEST IF IT's ALL BLACK int[] buffer = new int[bm.getWidth() * bm.getHeight()]; bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight()); boolean allBlack = true; for (int i = 0; i < buffer.length; i++) { if (buffer[i] != Color.BLACK) { allBlack = false; break; } } if (allBlack) { Slog.i(TAG, "Screenshot " + appWin + " was all black! mSurfaceLayer=" + (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null")); } } rawss.recycle(); return bm; } Loading Loading @@ -7408,6 +7485,7 @@ public class WindowManagerService extends IWindowManager.Stub performLayoutAndPlaceSurfacesLocked(); } @Override public void setOverscan(int displayId, int left, int top, int right, int bottom) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.WRITE_SECURE_SETTINGS) != Loading