• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.draganddrop;
18 
19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
21 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
22 import static android.content.ClipDescription.EXTRA_HIDE_DRAG_SOURCE_TASK_ID;
23 
24 import android.app.ActivityManager;
25 import android.app.ActivityTaskManager;
26 import android.app.PendingIntent;
27 import android.app.WindowConfiguration;
28 import android.content.ClipData;
29 import android.content.ClipDescription;
30 import android.content.Intent;
31 import android.content.pm.ActivityInfo;
32 
33 import androidx.annotation.Nullable;
34 
35 import com.android.internal.protolog.ProtoLog;
36 import com.android.wm.shell.common.DisplayLayout;
37 import com.android.wm.shell.protolog.ShellProtoLogGroup;
38 
39 import java.util.List;
40 
41 /**
42  * Per-drag session data.
43  */
44 public class DragSession {
45     private final ActivityTaskManager mActivityTaskManager;
46     @Nullable
47     private final ClipData mInitialDragData;
48     private final int mInitialDragFlags;
49 
50     final DisplayLayout displayLayout;
51     // The activity info associated with the activity in the appData or the launchableIntent
52     @Nullable
53     ActivityInfo activityInfo;
54     // The intent bundle that includes data about an app-type drag that is started by
55     // Launcher/SysUI.  Only one of appDragData OR launchableIntent will be non-null for a session.
56     @Nullable
57     Intent appData;
58     // A launchable intent that is specified in the ClipData directly.
59     // Only one of appDragData OR launchableIntent will be non-null for a session.
60     @Nullable
61     PendingIntent launchableIntent;
62     // Stores the current running task at the time that the drag was initiated
63     ActivityManager.RunningTaskInfo runningTaskInfo;
64     @WindowConfiguration.WindowingMode
65     int runningTaskWinMode = WINDOWING_MODE_UNDEFINED;
66     @WindowConfiguration.ActivityType
67     int runningTaskActType = ACTIVITY_TYPE_STANDARD;
68     boolean dragItemSupportsSplitscreen;
69     final int hideDragSourceTaskId;
70 
DragSession(ActivityTaskManager activityTaskManager, DisplayLayout dispLayout, ClipData data, int dragFlags)71     DragSession(ActivityTaskManager activityTaskManager,
72             DisplayLayout dispLayout, ClipData data, int dragFlags) {
73         mActivityTaskManager = activityTaskManager;
74         mInitialDragData = data;
75         mInitialDragFlags = dragFlags;
76         displayLayout = dispLayout;
77         hideDragSourceTaskId = data != null && data.getDescription().getExtras() != null
78                 ? data.getDescription().getExtras().getInt(EXTRA_HIDE_DRAG_SOURCE_TASK_ID, -1)
79                 : -1;
80         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
81                 "Extracting drag source taskId: taskId=%d", hideDragSourceTaskId);
82     }
83 
84     /**
85      * Returns the clip description associated with the drag.
86      */
getClipDescription()87     ClipDescription getClipDescription() {
88         return mInitialDragData.getDescription();
89     }
90 
91     /**
92      * Updates the running task for this drag session.
93      */
updateRunningTask()94     void updateRunningTask() {
95         final boolean hideDragSourceTask = hideDragSourceTaskId != -1;
96         final List<ActivityManager.RunningTaskInfo> tasks =
97                 mActivityTaskManager.getTasks(5, false /* filterOnlyVisibleRecents */);
98         for (int i = 0; i < tasks.size(); i++) {
99             final ActivityManager.RunningTaskInfo task = tasks.get(i);
100             if (hideDragSourceTask && hideDragSourceTaskId == task.taskId) {
101                 ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
102                         "Skipping running task: id=%d component=%s", task.taskId,
103                         task.baseIntent != null ? task.baseIntent.getComponent() : "null");
104                 continue;
105             }
106             if (!task.isVisible) {
107                 // Skip invisible tasks
108                 continue;
109             }
110             if (task.configuration.windowConfiguration.isAlwaysOnTop()) {
111                 // Skip always-on-top floating tasks
112                 continue;
113             }
114             runningTaskInfo = task;
115             runningTaskWinMode = task.getWindowingMode();
116             runningTaskActType = task.getActivityType();
117             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
118                     "Running task: id=%d component=%s", task.taskId,
119                     task.baseIntent != null ? task.baseIntent.getComponent() : "null");
120             break;
121         }
122     }
123 
124     /**
125      * Updates the session data based on the current state of the system at the start of the drag.
126      */
initialize(boolean skipUpdateRunningTask)127     void initialize(boolean skipUpdateRunningTask) {
128         if (!skipUpdateRunningTask) {
129             updateRunningTask();
130         }
131 
132         activityInfo = mInitialDragData.getItemAt(0).getActivityInfo();
133         // TODO: This should technically check & respect config_supportsNonResizableMultiWindow
134         dragItemSupportsSplitscreen = activityInfo == null
135                 || ActivityInfo.isResizeableMode(activityInfo.resizeMode);
136         appData = mInitialDragData.getItemAt(0).getIntent();
137         launchableIntent = DragUtils.getLaunchIntent(mInitialDragData, mInitialDragFlags);
138     }
139 }
140