Loading core/java/android/app/IActivityTaskManager.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationAdapter; import android.window.IWindowOrganizerController; import android.window.ITaskSnapshotManager; import android.window.BackAnimationAdapter; import android.window.BackNavigationInfo; import android.window.SplashScreenView; Loading Loading @@ -247,6 +248,10 @@ interface IActivityTaskManager { /** Returns an interface enabling the management of window organizers. */ IWindowOrganizerController getWindowOrganizerController(); /** Returns an interface enabling the access of task snapshots. */ @EnforcePermission(allOf={"MANAGE_ACTIVITY_TASKS", "READ_FRAME_BUFFER"}) ITaskSnapshotManager getTaskSnapshotManager(); boolean supportsLocalVoiceInteraction(); // Requests the "Open in browser" education to be shown Loading core/java/android/window/ITaskSnapshotManager.aidl 0 → 100644 +49 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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 android.window; /** * @hide */ interface ITaskSnapshotManager { /** * Fetches the snapshot for the task with the given id. * * @param taskId the id of the task to retrieve for * @param retrieveResolution the resolution we want to load. * * @throws RemoteException * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * screenshot can be found. */ android.window.TaskSnapshot getTaskSnapshot(int taskId, int retrieveResolution); /** * Requests for a new snapshot to be taken for the task with the given id, storing it in the * task snapshot cache only if requested. * * @param taskId the id of the task to take a snapshot of * @param updateCache Whether to store the new snapshot in the system's task snapshot cache. * If it is true, the snapshot can be either real content or app-theme mode * depending on the attributes of app. Otherwise, the snapshot will be taken * with real content. * @throws RemoteException * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * corresponding task can be found. */ android.window.TaskSnapshot takeTaskSnapshot(int taskId, boolean updateCache); } No newline at end of file core/java/android/window/TaskSnapshotManager.java 0 → 100644 +151 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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 android.window; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityTaskManager; import android.os.RemoteException; import android.util.Singleton; import android.util.Slog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Retrieve or request app snapshots in system. * * @hide */ public class TaskSnapshotManager { private static final String TAG = "TaskSnapshotManager"; /** * Set or retrieve the high resolution snapshot. */ public static final int RESOLUTION_HIGH = 1; /** * Set or retrieve the low resolution snapshot. */ public static final int RESOLUTION_LOW = 2; /** * Retrieve in any resolution. */ public static final int RESOLUTION_ANY = 3; /** * Flags for which kind of resolution snapshot. * * @hide */ @IntDef(prefix = { "RESOLUTION_" }, value = { RESOLUTION_HIGH, RESOLUTION_LOW, RESOLUTION_ANY }) @Retention(RetentionPolicy.SOURCE) public @interface Resolution {} private static final TaskSnapshotManager sInstance = new TaskSnapshotManager(); private TaskSnapshotManager() { } public static TaskSnapshotManager getInstance() { return sInstance; } /** * Fetches the snapshot for the task with the given id. * * @param taskId the id of the task to retrieve for * @param retrieveResolution the resolution we want to load. * * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * screenshot can be found. */ public TaskSnapshot getTaskSnapshot(int taskId, @Resolution int retrieveResolution) throws RemoteException { final TaskSnapshot t; try { t = ISnapshotManagerSingleton.get().getTaskSnapshot(taskId, retrieveResolution); } catch (RemoteException r) { Slog.e(TAG, "getTaskSnapshot fail: " + r); throw r; } return t; } /** * Requests for a new snapshot to be taken for the task with the given id, storing it in the * task snapshot cache only if requested. * * @param taskId the id of the task to take a snapshot of * @param updateCache Whether to store the new snapshot in the system's task snapshot cache. * If it is true, the snapshot can be either real content or app-theme mode * depending on the attributes of app. Otherwise, the snapshot will be taken * with real content. * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * corresponding task can be found. */ public TaskSnapshot takeTaskSnapshot(int taskId, boolean updateCache) throws RemoteException { final TaskSnapshot t; try { t = ISnapshotManagerSingleton.get().takeTaskSnapshot(taskId, updateCache); } catch (RemoteException r) { Slog.e(TAG, "getTaskSnapshot fail: " + r); throw r; } return t; } /** * @return Whether the resolution of snapshot align with requested resolution. */ public static boolean isResolutionMatch(@NonNull TaskSnapshot snapshot, @Resolution int retrieveResolution) { if (retrieveResolution == RESOLUTION_ANY) { return true; } final boolean isLowRes = snapshot.isLowResolution(); if (isLowRes) { return retrieveResolution == TaskSnapshotManager.RESOLUTION_LOW; } return true; } /** * @return Util method, convert the isLowResolution either FLAG_LOW_RES or FLAG_HIGH_RES. */ public static int convertRetrieveFlag(boolean isLowResolution) { return isLowResolution ? TaskSnapshotManager.RESOLUTION_LOW : TaskSnapshotManager.RESOLUTION_HIGH; } private static final Singleton<ITaskSnapshotManager> ISnapshotManagerSingleton = new Singleton<ITaskSnapshotManager>() { @Override protected ITaskSnapshotManager create() { try { return ActivityTaskManager.getService().getTaskSnapshotManager(); } catch (RemoteException e) { return null; } } }; } services/core/java/com/android/server/wm/ActivityRecord.java +9 −2 Original line number Diff line number Diff line Loading @@ -328,6 +328,7 @@ import android.window.SplashScreen; import android.window.SplashScreenView; import android.window.SplashScreenView.SplashScreenViewParcelable; import android.window.TaskSnapshot; import android.window.TaskSnapshotManager; import android.window.TransitionInfo.AnimationOptions; import android.window.WindowContainerToken; import android.window.WindowOnBackInvokedDispatcher; Loading Loading @@ -2284,8 +2285,14 @@ final class ActivityRecord extends WindowToken { return false; } final TaskSnapshot snapshot = mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, final TaskSnapshot snapshot; if (Flags.reduceTaskSnapshotMemoryUsage()) { snapshot = mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, TaskSnapshotManager.RESOLUTION_HIGH); } else { snapshot = mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, false /* isLowResolution */); } final int type = getStartingWindowType(newTask, taskSwitch, processRunning, allowTaskSnapshot, activityCreated, activityAllDrawn, snapshot); Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +29 −4 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ import static com.android.server.wm.WindowManagerService.MY_PID; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import android.Manifest; import android.annotation.EnforcePermission; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -242,9 +243,11 @@ import android.view.RemoteAnimationDefinition; import android.view.WindowManager; import android.window.BackAnimationAdapter; import android.window.BackNavigationInfo; import android.window.ITaskSnapshotManager; import android.window.IWindowOrganizerController; import android.window.SplashScreenView.SplashScreenViewParcelable; import android.window.TaskSnapshot; import android.window.TaskSnapshotManager; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -3993,6 +3996,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mWindowOrganizerController; } @EnforcePermission(allOf = {MANAGE_ACTIVITY_TASKS, READ_FRAME_BUFFER}) @Override public ITaskSnapshotManager getTaskSnapshotManager() { getTaskSnapshotManager_enforcePermission(); return mWindowManager.mSnapshotController.mSnapshotManagerService; } /** * Check that we have the features required for VR-related API calls, and throw an exception if * not. Loading Loading @@ -4082,8 +4092,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return null; } // Try to load snapshot from cache first, and add reference if the snapshot is in cache. final TaskSnapshot snapshot = mWindowManager.mTaskSnapshotController.getSnapshot(taskId, final TaskSnapshot snapshot; if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) { final int retrieveFlag = TaskSnapshotManager.convertRetrieveFlag(isLowResolution); snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( taskId, retrieveFlag, usage); } else { snapshot = mWindowManager.mTaskSnapshotController.getSnapshot(taskId, isLowResolution, usage); } if (snapshot != null) { return snapshot; } Loading @@ -4106,8 +4123,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found"); return null; } final TaskSnapshot snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( final TaskSnapshot snapshot; if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) { final int retrieveFlag = TaskSnapshotManager.convertRetrieveFlag( isLowResolution); snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( taskId, retrieveFlag, TaskSnapshot.REFERENCE_WRITE_TO_PARCEL); } else { snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( taskId, isLowResolution, TaskSnapshot.REFERENCE_WRITE_TO_PARCEL); } if (snapshot != null) { return snapshot; } Loading Loading
core/java/android/app/IActivityTaskManager.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationAdapter; import android.window.IWindowOrganizerController; import android.window.ITaskSnapshotManager; import android.window.BackAnimationAdapter; import android.window.BackNavigationInfo; import android.window.SplashScreenView; Loading Loading @@ -247,6 +248,10 @@ interface IActivityTaskManager { /** Returns an interface enabling the management of window organizers. */ IWindowOrganizerController getWindowOrganizerController(); /** Returns an interface enabling the access of task snapshots. */ @EnforcePermission(allOf={"MANAGE_ACTIVITY_TASKS", "READ_FRAME_BUFFER"}) ITaskSnapshotManager getTaskSnapshotManager(); boolean supportsLocalVoiceInteraction(); // Requests the "Open in browser" education to be shown Loading
core/java/android/window/ITaskSnapshotManager.aidl 0 → 100644 +49 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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 android.window; /** * @hide */ interface ITaskSnapshotManager { /** * Fetches the snapshot for the task with the given id. * * @param taskId the id of the task to retrieve for * @param retrieveResolution the resolution we want to load. * * @throws RemoteException * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * screenshot can be found. */ android.window.TaskSnapshot getTaskSnapshot(int taskId, int retrieveResolution); /** * Requests for a new snapshot to be taken for the task with the given id, storing it in the * task snapshot cache only if requested. * * @param taskId the id of the task to take a snapshot of * @param updateCache Whether to store the new snapshot in the system's task snapshot cache. * If it is true, the snapshot can be either real content or app-theme mode * depending on the attributes of app. Otherwise, the snapshot will be taken * with real content. * @throws RemoteException * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * corresponding task can be found. */ android.window.TaskSnapshot takeTaskSnapshot(int taskId, boolean updateCache); } No newline at end of file
core/java/android/window/TaskSnapshotManager.java 0 → 100644 +151 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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 android.window; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityTaskManager; import android.os.RemoteException; import android.util.Singleton; import android.util.Slog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Retrieve or request app snapshots in system. * * @hide */ public class TaskSnapshotManager { private static final String TAG = "TaskSnapshotManager"; /** * Set or retrieve the high resolution snapshot. */ public static final int RESOLUTION_HIGH = 1; /** * Set or retrieve the low resolution snapshot. */ public static final int RESOLUTION_LOW = 2; /** * Retrieve in any resolution. */ public static final int RESOLUTION_ANY = 3; /** * Flags for which kind of resolution snapshot. * * @hide */ @IntDef(prefix = { "RESOLUTION_" }, value = { RESOLUTION_HIGH, RESOLUTION_LOW, RESOLUTION_ANY }) @Retention(RetentionPolicy.SOURCE) public @interface Resolution {} private static final TaskSnapshotManager sInstance = new TaskSnapshotManager(); private TaskSnapshotManager() { } public static TaskSnapshotManager getInstance() { return sInstance; } /** * Fetches the snapshot for the task with the given id. * * @param taskId the id of the task to retrieve for * @param retrieveResolution the resolution we want to load. * * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * screenshot can be found. */ public TaskSnapshot getTaskSnapshot(int taskId, @Resolution int retrieveResolution) throws RemoteException { final TaskSnapshot t; try { t = ISnapshotManagerSingleton.get().getTaskSnapshot(taskId, retrieveResolution); } catch (RemoteException r) { Slog.e(TAG, "getTaskSnapshot fail: " + r); throw r; } return t; } /** * Requests for a new snapshot to be taken for the task with the given id, storing it in the * task snapshot cache only if requested. * * @param taskId the id of the task to take a snapshot of * @param updateCache Whether to store the new snapshot in the system's task snapshot cache. * If it is true, the snapshot can be either real content or app-theme mode * depending on the attributes of app. Otherwise, the snapshot will be taken * with real content. * @return a graphic buffer representing a screenshot of a task, or {@code null} if no * corresponding task can be found. */ public TaskSnapshot takeTaskSnapshot(int taskId, boolean updateCache) throws RemoteException { final TaskSnapshot t; try { t = ISnapshotManagerSingleton.get().takeTaskSnapshot(taskId, updateCache); } catch (RemoteException r) { Slog.e(TAG, "getTaskSnapshot fail: " + r); throw r; } return t; } /** * @return Whether the resolution of snapshot align with requested resolution. */ public static boolean isResolutionMatch(@NonNull TaskSnapshot snapshot, @Resolution int retrieveResolution) { if (retrieveResolution == RESOLUTION_ANY) { return true; } final boolean isLowRes = snapshot.isLowResolution(); if (isLowRes) { return retrieveResolution == TaskSnapshotManager.RESOLUTION_LOW; } return true; } /** * @return Util method, convert the isLowResolution either FLAG_LOW_RES or FLAG_HIGH_RES. */ public static int convertRetrieveFlag(boolean isLowResolution) { return isLowResolution ? TaskSnapshotManager.RESOLUTION_LOW : TaskSnapshotManager.RESOLUTION_HIGH; } private static final Singleton<ITaskSnapshotManager> ISnapshotManagerSingleton = new Singleton<ITaskSnapshotManager>() { @Override protected ITaskSnapshotManager create() { try { return ActivityTaskManager.getService().getTaskSnapshotManager(); } catch (RemoteException e) { return null; } } }; }
services/core/java/com/android/server/wm/ActivityRecord.java +9 −2 Original line number Diff line number Diff line Loading @@ -328,6 +328,7 @@ import android.window.SplashScreen; import android.window.SplashScreenView; import android.window.SplashScreenView.SplashScreenViewParcelable; import android.window.TaskSnapshot; import android.window.TaskSnapshotManager; import android.window.TransitionInfo.AnimationOptions; import android.window.WindowContainerToken; import android.window.WindowOnBackInvokedDispatcher; Loading Loading @@ -2284,8 +2285,14 @@ final class ActivityRecord extends WindowToken { return false; } final TaskSnapshot snapshot = mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, final TaskSnapshot snapshot; if (Flags.reduceTaskSnapshotMemoryUsage()) { snapshot = mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, TaskSnapshotManager.RESOLUTION_HIGH); } else { snapshot = mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, false /* isLowResolution */); } final int type = getStartingWindowType(newTask, taskSwitch, processRunning, allowTaskSnapshot, activityCreated, activityAllDrawn, snapshot); Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +29 −4 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ import static com.android.server.wm.WindowManagerService.MY_PID; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import android.Manifest; import android.annotation.EnforcePermission; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -242,9 +243,11 @@ import android.view.RemoteAnimationDefinition; import android.view.WindowManager; import android.window.BackAnimationAdapter; import android.window.BackNavigationInfo; import android.window.ITaskSnapshotManager; import android.window.IWindowOrganizerController; import android.window.SplashScreenView.SplashScreenViewParcelable; import android.window.TaskSnapshot; import android.window.TaskSnapshotManager; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -3993,6 +3996,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mWindowOrganizerController; } @EnforcePermission(allOf = {MANAGE_ACTIVITY_TASKS, READ_FRAME_BUFFER}) @Override public ITaskSnapshotManager getTaskSnapshotManager() { getTaskSnapshotManager_enforcePermission(); return mWindowManager.mSnapshotController.mSnapshotManagerService; } /** * Check that we have the features required for VR-related API calls, and throw an exception if * not. Loading Loading @@ -4082,8 +4092,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return null; } // Try to load snapshot from cache first, and add reference if the snapshot is in cache. final TaskSnapshot snapshot = mWindowManager.mTaskSnapshotController.getSnapshot(taskId, final TaskSnapshot snapshot; if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) { final int retrieveFlag = TaskSnapshotManager.convertRetrieveFlag(isLowResolution); snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( taskId, retrieveFlag, usage); } else { snapshot = mWindowManager.mTaskSnapshotController.getSnapshot(taskId, isLowResolution, usage); } if (snapshot != null) { return snapshot; } Loading @@ -4106,8 +4123,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found"); return null; } final TaskSnapshot snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( final TaskSnapshot snapshot; if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) { final int retrieveFlag = TaskSnapshotManager.convertRetrieveFlag( isLowResolution); snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( taskId, retrieveFlag, TaskSnapshot.REFERENCE_WRITE_TO_PARCEL); } else { snapshot = mWindowManager.mTaskSnapshotController.getSnapshot( taskId, isLowResolution, TaskSnapshot.REFERENCE_WRITE_TO_PARCEL); } if (snapshot != null) { return snapshot; } Loading