Loading services/core/java/com/android/server/wm/TaskSnapshotController.java +9 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.server.wm; import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS; import static com.android.server.wm.TaskSnapshotPersister.DISABLE_FULL_SIZED_BITMAPS; import static com.android.server.wm.TaskSnapshotPersister.REDUCED_SCALE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; Loading Loading @@ -188,7 +190,8 @@ class TaskSnapshotController { */ @Nullable TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk, boolean reducedResolution) { return mCache.getSnapshot(taskId, userId, restoreFromDisk, reducedResolution); return mCache.getSnapshot(taskId, userId, restoreFromDisk, reducedResolution || DISABLE_FULL_SIZED_BITMAPS); } /** Loading @@ -209,14 +212,16 @@ class TaskSnapshotController { if (mainWindow == null) { return null; } final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic(); final float scaleFraction = isLowRamDevice ? REDUCED_SCALE : 1f; final GraphicBuffer buffer = top.mDisplayContent.screenshotApplicationsToBuffer(top.token, -1, -1, false, 1.0f, false, true); -1, -1, false, scaleFraction, false, true); if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) { return null; } return new TaskSnapshot(buffer, top.getConfiguration().orientation, minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */, 1f /* scale */); minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), isLowRamDevice /* reduced */, scaleFraction /* scale */); } private boolean shouldDisableSnapshots() { Loading services/core/java/com/android/server/wm/TaskSnapshotPersister.java +34 −10 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.TestApi; import android.app.ActivityManager; import android.app.ActivityManager.TaskSnapshot; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; Loading Loading @@ -53,6 +54,7 @@ class TaskSnapshotPersister { private static final String SNAPSHOTS_DIRNAME = "snapshots"; private static final String REDUCED_POSTFIX = "_reduced"; static final float REDUCED_SCALE = 0.5f; static final boolean DISABLE_FULL_SIZED_BITMAPS = ActivityManager.isLowRamDeviceStatic(); private static final long DELAY_MS = 100; private static final int QUALITY = 95; private static final String PROTO_EXTENSION = ".proto"; Loading Loading @@ -183,6 +185,11 @@ class TaskSnapshotPersister { } File getBitmapFile(int taskId, int userId) { // Full sized bitmaps are disabled on low ram devices if (DISABLE_FULL_SIZED_BITMAPS) { Slog.wtf(TAG, "This device does not support full sized resolution bitmaps."); return null; } return new File(getDirectory(userId), taskId + BITMAP_EXTENSION); } Loading @@ -197,11 +204,15 @@ class TaskSnapshotPersister { private void deleteSnapshot(int taskId, int userId) { final File protoFile = getProtoFile(taskId, userId); final File bitmapFile = getBitmapFile(taskId, userId); final File bitmapReducedFile = getReducedResolutionBitmapFile(taskId, userId); protoFile.delete(); bitmapFile.delete(); bitmapReducedFile.delete(); // Low ram devices do not have a full sized file to delete if (!DISABLE_FULL_SIZED_BITMAPS) { final File bitmapFile = getBitmapFile(taskId, userId); bitmapFile.delete(); } } interface DirectoryResolver { Loading Loading @@ -323,7 +334,6 @@ class TaskSnapshotPersister { boolean writeBuffer() { final File file = getBitmapFile(mTaskId, mUserId); final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId); final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot()); if (bitmap == null) { Slog.e(TAG, "Invalid task snapshot hw bitmap"); Loading @@ -331,18 +341,32 @@ class TaskSnapshotPersister { } final Bitmap swBitmap = bitmap.copy(Config.ARGB_8888, false /* isMutable */); final Bitmap reduced = Bitmap.createScaledBitmap(swBitmap, final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId); final Bitmap reduced = mSnapshot.isReducedResolution() ? swBitmap : Bitmap.createScaledBitmap(swBitmap, (int) (bitmap.getWidth() * REDUCED_SCALE), (int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */); try { FileOutputStream fos = new FileOutputStream(file); swBitmap.compress(JPEG, QUALITY, fos); fos.close(); FileOutputStream reducedFos = new FileOutputStream(reducedFile); reduced.compress(JPEG, QUALITY, reducedFos); reducedFos.close(); } catch (IOException e) { Slog.e(TAG, "Unable to open " + file + " or " + reducedFile +" for persisting.", e); Slog.e(TAG, "Unable to open " + reducedFile +" for persisting.", e); return false; } // For snapshots with reduced resolution, do not create or save full sized bitmaps if (mSnapshot.isReducedResolution()) { return true; } try { FileOutputStream fos = new FileOutputStream(file); swBitmap.compress(JPEG, QUALITY, fos); fos.close(); } catch (IOException e) { Slog.e(TAG, "Unable to open " + file + " for persisting.", e); return false; } return true; Loading services/core/java/com/android/server/wm/TaskSnapshotSurface.java +23 −2 Original line number Diff line number Diff line Loading @@ -320,6 +320,10 @@ class TaskSnapshotSurface implements StartingSurface { mChildSurfaceControl.show(); mChildSurfaceControl.setWindowCrop(crop); mChildSurfaceControl.setPosition(frame.left, frame.top); // Scale the mismatch dimensions to fill the task bounds final float scale = 1 / mSnapshot.getScale(); mChildSurfaceControl.setMatrix(scale, 0, 0, scale); } finally { SurfaceControl.closeTransaction(); } Loading @@ -332,6 +336,11 @@ class TaskSnapshotSurface implements StartingSurface { mSurface.release(); } /** * Calculates the snapshot crop in snapshot coordinate space. * * @return crop rect in snapshot coordinate space. */ @VisibleForTesting Rect calculateSnapshotCrop() { final Rect rect = new Rect(); Loading @@ -340,16 +349,28 @@ class TaskSnapshotSurface implements StartingSurface { // Let's remove all system decorations except the status bar, but only if the task is at the // very top of the screen. rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom); rect.inset((int) (insets.left * mSnapshot.getScale()), mTaskBounds.top != 0 ? (int) (insets.top * mSnapshot.getScale()) : 0, (int) (insets.right * mSnapshot.getScale()), (int) (insets.bottom * mSnapshot.getScale())); return rect; } /** * Calculates the snapshot frame in window coordinate space from crop. * * @param crop rect that is in snapshot coordinate space. */ @VisibleForTesting Rect calculateSnapshotFrame(Rect crop) { final Rect frame = new Rect(crop); final float scale = mSnapshot.getScale(); // Rescale the frame from snapshot to window coordinate space frame.scale(1 / scale); // By default, offset it to to top/left corner frame.offsetTo(-crop.left, -crop.top); frame.offsetTo((int) (-crop.left / scale), (int) (-crop.top / scale)); // However, we also need to make space for the navigation bar on the left side. final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left, Loading Loading
services/core/java/com/android/server/wm/TaskSnapshotController.java +9 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.server.wm; import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS; import static com.android.server.wm.TaskSnapshotPersister.DISABLE_FULL_SIZED_BITMAPS; import static com.android.server.wm.TaskSnapshotPersister.REDUCED_SCALE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; Loading Loading @@ -188,7 +190,8 @@ class TaskSnapshotController { */ @Nullable TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk, boolean reducedResolution) { return mCache.getSnapshot(taskId, userId, restoreFromDisk, reducedResolution); return mCache.getSnapshot(taskId, userId, restoreFromDisk, reducedResolution || DISABLE_FULL_SIZED_BITMAPS); } /** Loading @@ -209,14 +212,16 @@ class TaskSnapshotController { if (mainWindow == null) { return null; } final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic(); final float scaleFraction = isLowRamDevice ? REDUCED_SCALE : 1f; final GraphicBuffer buffer = top.mDisplayContent.screenshotApplicationsToBuffer(top.token, -1, -1, false, 1.0f, false, true); -1, -1, false, scaleFraction, false, true); if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) { return null; } return new TaskSnapshot(buffer, top.getConfiguration().orientation, minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */, 1f /* scale */); minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), isLowRamDevice /* reduced */, scaleFraction /* scale */); } private boolean shouldDisableSnapshots() { Loading
services/core/java/com/android/server/wm/TaskSnapshotPersister.java +34 −10 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.TestApi; import android.app.ActivityManager; import android.app.ActivityManager.TaskSnapshot; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; Loading Loading @@ -53,6 +54,7 @@ class TaskSnapshotPersister { private static final String SNAPSHOTS_DIRNAME = "snapshots"; private static final String REDUCED_POSTFIX = "_reduced"; static final float REDUCED_SCALE = 0.5f; static final boolean DISABLE_FULL_SIZED_BITMAPS = ActivityManager.isLowRamDeviceStatic(); private static final long DELAY_MS = 100; private static final int QUALITY = 95; private static final String PROTO_EXTENSION = ".proto"; Loading Loading @@ -183,6 +185,11 @@ class TaskSnapshotPersister { } File getBitmapFile(int taskId, int userId) { // Full sized bitmaps are disabled on low ram devices if (DISABLE_FULL_SIZED_BITMAPS) { Slog.wtf(TAG, "This device does not support full sized resolution bitmaps."); return null; } return new File(getDirectory(userId), taskId + BITMAP_EXTENSION); } Loading @@ -197,11 +204,15 @@ class TaskSnapshotPersister { private void deleteSnapshot(int taskId, int userId) { final File protoFile = getProtoFile(taskId, userId); final File bitmapFile = getBitmapFile(taskId, userId); final File bitmapReducedFile = getReducedResolutionBitmapFile(taskId, userId); protoFile.delete(); bitmapFile.delete(); bitmapReducedFile.delete(); // Low ram devices do not have a full sized file to delete if (!DISABLE_FULL_SIZED_BITMAPS) { final File bitmapFile = getBitmapFile(taskId, userId); bitmapFile.delete(); } } interface DirectoryResolver { Loading Loading @@ -323,7 +334,6 @@ class TaskSnapshotPersister { boolean writeBuffer() { final File file = getBitmapFile(mTaskId, mUserId); final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId); final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot()); if (bitmap == null) { Slog.e(TAG, "Invalid task snapshot hw bitmap"); Loading @@ -331,18 +341,32 @@ class TaskSnapshotPersister { } final Bitmap swBitmap = bitmap.copy(Config.ARGB_8888, false /* isMutable */); final Bitmap reduced = Bitmap.createScaledBitmap(swBitmap, final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId); final Bitmap reduced = mSnapshot.isReducedResolution() ? swBitmap : Bitmap.createScaledBitmap(swBitmap, (int) (bitmap.getWidth() * REDUCED_SCALE), (int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */); try { FileOutputStream fos = new FileOutputStream(file); swBitmap.compress(JPEG, QUALITY, fos); fos.close(); FileOutputStream reducedFos = new FileOutputStream(reducedFile); reduced.compress(JPEG, QUALITY, reducedFos); reducedFos.close(); } catch (IOException e) { Slog.e(TAG, "Unable to open " + file + " or " + reducedFile +" for persisting.", e); Slog.e(TAG, "Unable to open " + reducedFile +" for persisting.", e); return false; } // For snapshots with reduced resolution, do not create or save full sized bitmaps if (mSnapshot.isReducedResolution()) { return true; } try { FileOutputStream fos = new FileOutputStream(file); swBitmap.compress(JPEG, QUALITY, fos); fos.close(); } catch (IOException e) { Slog.e(TAG, "Unable to open " + file + " for persisting.", e); return false; } return true; Loading
services/core/java/com/android/server/wm/TaskSnapshotSurface.java +23 −2 Original line number Diff line number Diff line Loading @@ -320,6 +320,10 @@ class TaskSnapshotSurface implements StartingSurface { mChildSurfaceControl.show(); mChildSurfaceControl.setWindowCrop(crop); mChildSurfaceControl.setPosition(frame.left, frame.top); // Scale the mismatch dimensions to fill the task bounds final float scale = 1 / mSnapshot.getScale(); mChildSurfaceControl.setMatrix(scale, 0, 0, scale); } finally { SurfaceControl.closeTransaction(); } Loading @@ -332,6 +336,11 @@ class TaskSnapshotSurface implements StartingSurface { mSurface.release(); } /** * Calculates the snapshot crop in snapshot coordinate space. * * @return crop rect in snapshot coordinate space. */ @VisibleForTesting Rect calculateSnapshotCrop() { final Rect rect = new Rect(); Loading @@ -340,16 +349,28 @@ class TaskSnapshotSurface implements StartingSurface { // Let's remove all system decorations except the status bar, but only if the task is at the // very top of the screen. rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom); rect.inset((int) (insets.left * mSnapshot.getScale()), mTaskBounds.top != 0 ? (int) (insets.top * mSnapshot.getScale()) : 0, (int) (insets.right * mSnapshot.getScale()), (int) (insets.bottom * mSnapshot.getScale())); return rect; } /** * Calculates the snapshot frame in window coordinate space from crop. * * @param crop rect that is in snapshot coordinate space. */ @VisibleForTesting Rect calculateSnapshotFrame(Rect crop) { final Rect frame = new Rect(crop); final float scale = mSnapshot.getScale(); // Rescale the frame from snapshot to window coordinate space frame.scale(1 / scale); // By default, offset it to to top/left corner frame.offsetTo(-crop.left, -crop.top); frame.offsetTo((int) (-crop.left / scale), (int) (-crop.top / scale)); // However, we also need to make space for the navigation bar on the left side. final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left, Loading