Loading core/res/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3253,6 +3253,9 @@ <!-- Feature flag to store TaskSnapshot in 16 bit pixel format to save memory. --> <bool name="config_use16BitTaskSnapshotPixelFormat">false</bool> <!-- The amount to scale fullscreen activity snapshot for predict-back animation. --> <item name="config_resActivitySnapshotScale" format="float" type="dimen">0.6</item> <!-- Determines whether recent tasks are provided to the user. Default device has recents property. If this is false, then the following recents config flags are ignored. --> <bool name="config_hasRecents">true</bool> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -362,6 +362,7 @@ <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/> <java-symbol type="dimen" name="config_highResTaskSnapshotScale" /> <java-symbol type="dimen" name="config_lowResTaskSnapshotScale" /> <java-symbol type="dimen" name="config_resActivitySnapshotScale" /> <java-symbol type="dimen" name="config_qsTileStrokeWidthInactive" /> <java-symbol type="dimen" name="config_qsTileStrokeWidthActive" /> <java-symbol type="bool" name="config_use16BitTaskSnapshotPixelFormat" /> Loading services/core/java/com/android/server/wm/AbsAppSnapshotController.java +32 −12 Original line number Diff line number Diff line Loading @@ -55,8 +55,8 @@ import java.io.PrintWriter; * @param <CACHE> The basic cache for either Task or ActivityRecord */ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, CACHE extends AbsAppSnapshotCache<TYPE>> { private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotController" : TAG_WM; CACHE extends SnapshotCache<TYPE>> { static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotController" : TAG_WM; /** * Return value for {@link #getSnapshotMode}: We are allowed to take a real screenshot to be * used as the snapshot. Loading @@ -76,7 +76,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, static final int SNAPSHOT_MODE_NONE = 2; protected final WindowManagerService mService; protected final float mHighResTaskSnapshotScale; protected final float mHighResSnapshotScale; private final Rect mTmpRect = new Rect(); /** * Flag indicating whether we are running on an Android TV device. Loading @@ -99,12 +99,13 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, PackageManager.FEATURE_LEANBACK); mIsRunningOnIoT = mService.mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_EMBEDDED); mHighResTaskSnapshotScale = initSnapshotScale(); mHighResSnapshotScale = initSnapshotScale(); } protected float initSnapshotScale() { return mService.mContext.getResources().getFloat( final float config = mService.mContext.getResources().getFloat( com.android.internal.R.dimen.config_highResTaskSnapshotScale); return Math.max(Math.min(config, 1f), 0.1f); } /** Loading Loading @@ -173,7 +174,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, final HardwareBuffer buffer = snapshot.getHardwareBuffer(); if (buffer.getWidth() == 0 || buffer.getHeight() == 0) { buffer.close(); Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x" Slog.e(TAG, "Invalid snapshot dimensions " + buffer.getWidth() + "x" + buffer.getHeight()); return null; } else { Loading Loading @@ -223,7 +224,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, Point taskSize = new Point(); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "createSnapshot"); final ScreenCapture.ScreenshotHardwareBuffer taskSnapshot = createSnapshot(source, mHighResTaskSnapshotScale, builder.getPixelFormat(), taskSize, builder); mHighResSnapshotScale, builder.getPixelFormat(), taskSize, builder); Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); builder.setTaskSize(taskSize); return taskSnapshot; Loading Loading @@ -397,11 +398,11 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, final SnapshotDrawerUtils.SystemBarBackgroundPainter decorPainter = new SnapshotDrawerUtils.SystemBarBackgroundPainter(attrs.flags, attrs.privateFlags, attrs.insetsFlags.appearance, taskDescription, mHighResTaskSnapshotScale, mainWindow.getRequestedVisibleTypes()); mHighResSnapshotScale, mainWindow.getRequestedVisibleTypes()); final int taskWidth = taskBounds.width(); final int taskHeight = taskBounds.height(); final int width = (int) (taskWidth * mHighResTaskSnapshotScale); final int height = (int) (taskHeight * mHighResTaskSnapshotScale); final int width = (int) (taskWidth * mHighResSnapshotScale); final int height = (int) (taskHeight * mHighResSnapshotScale); final RenderNode node = RenderNode.create("SnapshotController", null); node.setLeftTopRightBottom(0, 0, width, height); node.setClipToBounds(false); Loading Loading @@ -450,9 +451,28 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, return 0; } /** * Called when an {@link ActivityRecord} has been removed. */ void onAppRemoved(ActivityRecord activity) { mCache.onAppRemoved(activity); } /** * Called when the process of an {@link ActivityRecord} has died. */ void onAppDied(ActivityRecord activity) { mCache.onAppDied(activity); } boolean isAnimatingByRecents(@NonNull Task task) { return task.isAnimatingByRecents() || mService.mAtmService.getTransitionController().inRecentsTransition(task); } void dump(PrintWriter pw, String prefix) { pw.println(prefix + "mHighResTaskSnapshotScale=" + mHighResTaskSnapshotScale); pw.println(prefix + "mTaskSnapshotEnabled=" + mSnapshotEnabled); pw.println(prefix + "mHighResSnapshotScale=" + mHighResSnapshotScale); pw.println(prefix + "mSnapshotEnabled=" + mSnapshotEnabled); mCache.dump(pw, prefix); } } services/core/java/com/android/server/wm/ActivityRecord.java +15 −2 Original line number Diff line number Diff line Loading @@ -4223,7 +4223,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A getDisplayContent().mOpeningApps.remove(this); getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this); mWmService.mTaskSnapshotController.onAppRemoved(this); mWmService.mSnapshotController.onAppRemoved(this); mTaskSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this); mTaskSupervisor.mStoppingActivities.remove(this); waitingToShow = false; Loading Loading @@ -5557,7 +5558,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A && !fromTransition) { // Take the screenshot before possibly hiding the WSA, otherwise the screenshot // will not be taken. mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible); mWmService.mSnapshotController.notifyAppVisibilityChanged(this, visible); } // If we are hidden but there is no delay needed we immediately Loading Loading @@ -10465,6 +10466,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A && !inPinnedWindowingMode() && !inFreeformWindowingMode(); } boolean canCaptureSnapshot() { if (!isSurfaceShowing() || findMainWindow() == null) { return false; } return forAllWindows( // Ensure at least one window for the top app is visible before attempting to // take a screenshot. Visible here means that the WSA surface is shown and has // an alpha greater than 0. ws -> ws.mWinAnimator != null && ws.mWinAnimator.getShown() && ws.mWinAnimator.mLastAlpha > 0f, true /* traverseTopToBottom */); } void overrideCustomTransition(boolean open, int enterAnim, int exitAnim, int backgroundColor) { CustomAppTransition transition = getCustomAnimation(open); if (transition == null) { Loading services/core/java/com/android/server/wm/ActivitySnapshotCache.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import android.window.TaskSnapshot; /** * A snapshot cache for activity, the token is the hashCode of the activity. */ class ActivitySnapshotCache extends SnapshotCache<ActivityRecord> { ActivitySnapshotCache(WindowManagerService service) { super(service, "Activity"); } @Override void putSnapshot(ActivityRecord ar, TaskSnapshot snapshot) { final int hasCode = System.identityHashCode(ar); final CacheEntry entry = mRunningCache.get(hasCode); if (entry != null) { mAppIdMap.remove(entry.topApp); } mAppIdMap.put(ar, hasCode); mRunningCache.put(hasCode, new CacheEntry(snapshot, ar)); } } Loading
core/res/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3253,6 +3253,9 @@ <!-- Feature flag to store TaskSnapshot in 16 bit pixel format to save memory. --> <bool name="config_use16BitTaskSnapshotPixelFormat">false</bool> <!-- The amount to scale fullscreen activity snapshot for predict-back animation. --> <item name="config_resActivitySnapshotScale" format="float" type="dimen">0.6</item> <!-- Determines whether recent tasks are provided to the user. Default device has recents property. If this is false, then the following recents config flags are ignored. --> <bool name="config_hasRecents">true</bool> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -362,6 +362,7 @@ <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/> <java-symbol type="dimen" name="config_highResTaskSnapshotScale" /> <java-symbol type="dimen" name="config_lowResTaskSnapshotScale" /> <java-symbol type="dimen" name="config_resActivitySnapshotScale" /> <java-symbol type="dimen" name="config_qsTileStrokeWidthInactive" /> <java-symbol type="dimen" name="config_qsTileStrokeWidthActive" /> <java-symbol type="bool" name="config_use16BitTaskSnapshotPixelFormat" /> Loading
services/core/java/com/android/server/wm/AbsAppSnapshotController.java +32 −12 Original line number Diff line number Diff line Loading @@ -55,8 +55,8 @@ import java.io.PrintWriter; * @param <CACHE> The basic cache for either Task or ActivityRecord */ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, CACHE extends AbsAppSnapshotCache<TYPE>> { private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotController" : TAG_WM; CACHE extends SnapshotCache<TYPE>> { static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotController" : TAG_WM; /** * Return value for {@link #getSnapshotMode}: We are allowed to take a real screenshot to be * used as the snapshot. Loading @@ -76,7 +76,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, static final int SNAPSHOT_MODE_NONE = 2; protected final WindowManagerService mService; protected final float mHighResTaskSnapshotScale; protected final float mHighResSnapshotScale; private final Rect mTmpRect = new Rect(); /** * Flag indicating whether we are running on an Android TV device. Loading @@ -99,12 +99,13 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, PackageManager.FEATURE_LEANBACK); mIsRunningOnIoT = mService.mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_EMBEDDED); mHighResTaskSnapshotScale = initSnapshotScale(); mHighResSnapshotScale = initSnapshotScale(); } protected float initSnapshotScale() { return mService.mContext.getResources().getFloat( final float config = mService.mContext.getResources().getFloat( com.android.internal.R.dimen.config_highResTaskSnapshotScale); return Math.max(Math.min(config, 1f), 0.1f); } /** Loading Loading @@ -173,7 +174,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, final HardwareBuffer buffer = snapshot.getHardwareBuffer(); if (buffer.getWidth() == 0 || buffer.getHeight() == 0) { buffer.close(); Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x" Slog.e(TAG, "Invalid snapshot dimensions " + buffer.getWidth() + "x" + buffer.getHeight()); return null; } else { Loading Loading @@ -223,7 +224,7 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, Point taskSize = new Point(); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "createSnapshot"); final ScreenCapture.ScreenshotHardwareBuffer taskSnapshot = createSnapshot(source, mHighResTaskSnapshotScale, builder.getPixelFormat(), taskSize, builder); mHighResSnapshotScale, builder.getPixelFormat(), taskSize, builder); Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); builder.setTaskSize(taskSize); return taskSnapshot; Loading Loading @@ -397,11 +398,11 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, final SnapshotDrawerUtils.SystemBarBackgroundPainter decorPainter = new SnapshotDrawerUtils.SystemBarBackgroundPainter(attrs.flags, attrs.privateFlags, attrs.insetsFlags.appearance, taskDescription, mHighResTaskSnapshotScale, mainWindow.getRequestedVisibleTypes()); mHighResSnapshotScale, mainWindow.getRequestedVisibleTypes()); final int taskWidth = taskBounds.width(); final int taskHeight = taskBounds.height(); final int width = (int) (taskWidth * mHighResTaskSnapshotScale); final int height = (int) (taskHeight * mHighResTaskSnapshotScale); final int width = (int) (taskWidth * mHighResSnapshotScale); final int height = (int) (taskHeight * mHighResSnapshotScale); final RenderNode node = RenderNode.create("SnapshotController", null); node.setLeftTopRightBottom(0, 0, width, height); node.setClipToBounds(false); Loading Loading @@ -450,9 +451,28 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer, return 0; } /** * Called when an {@link ActivityRecord} has been removed. */ void onAppRemoved(ActivityRecord activity) { mCache.onAppRemoved(activity); } /** * Called when the process of an {@link ActivityRecord} has died. */ void onAppDied(ActivityRecord activity) { mCache.onAppDied(activity); } boolean isAnimatingByRecents(@NonNull Task task) { return task.isAnimatingByRecents() || mService.mAtmService.getTransitionController().inRecentsTransition(task); } void dump(PrintWriter pw, String prefix) { pw.println(prefix + "mHighResTaskSnapshotScale=" + mHighResTaskSnapshotScale); pw.println(prefix + "mTaskSnapshotEnabled=" + mSnapshotEnabled); pw.println(prefix + "mHighResSnapshotScale=" + mHighResSnapshotScale); pw.println(prefix + "mSnapshotEnabled=" + mSnapshotEnabled); mCache.dump(pw, prefix); } }
services/core/java/com/android/server/wm/ActivityRecord.java +15 −2 Original line number Diff line number Diff line Loading @@ -4223,7 +4223,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A getDisplayContent().mOpeningApps.remove(this); getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this); mWmService.mTaskSnapshotController.onAppRemoved(this); mWmService.mSnapshotController.onAppRemoved(this); mTaskSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this); mTaskSupervisor.mStoppingActivities.remove(this); waitingToShow = false; Loading Loading @@ -5557,7 +5558,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A && !fromTransition) { // Take the screenshot before possibly hiding the WSA, otherwise the screenshot // will not be taken. mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible); mWmService.mSnapshotController.notifyAppVisibilityChanged(this, visible); } // If we are hidden but there is no delay needed we immediately Loading Loading @@ -10465,6 +10466,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A && !inPinnedWindowingMode() && !inFreeformWindowingMode(); } boolean canCaptureSnapshot() { if (!isSurfaceShowing() || findMainWindow() == null) { return false; } return forAllWindows( // Ensure at least one window for the top app is visible before attempting to // take a screenshot. Visible here means that the WSA surface is shown and has // an alpha greater than 0. ws -> ws.mWinAnimator != null && ws.mWinAnimator.getShown() && ws.mWinAnimator.mLastAlpha > 0f, true /* traverseTopToBottom */); } void overrideCustomTransition(boolean open, int enterAnim, int exitAnim, int backgroundColor) { CustomAppTransition transition = getCustomAnimation(open); if (transition == null) { Loading
services/core/java/com/android/server/wm/ActivitySnapshotCache.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import android.window.TaskSnapshot; /** * A snapshot cache for activity, the token is the hashCode of the activity. */ class ActivitySnapshotCache extends SnapshotCache<ActivityRecord> { ActivitySnapshotCache(WindowManagerService service) { super(service, "Activity"); } @Override void putSnapshot(ActivityRecord ar, TaskSnapshot snapshot) { final int hasCode = System.identityHashCode(ar); final CacheEntry entry = mRunningCache.get(hasCode); if (entry != null) { mAppIdMap.remove(entry.topApp); } mAppIdMap.put(ar, hasCode); mRunningCache.put(hasCode, new CacheEntry(snapshot, ar)); } }