• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.server.wm;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.WindowConfiguration;
22 import android.content.Intent;
23 import android.content.pm.ActivityInfo;
24 import android.os.Process;
25 import android.os.UserHandle;
26 import android.util.ArraySet;
27 import android.util.Slog;
28 import android.window.DisplayWindowPolicyController;
29 
30 import java.io.PrintWriter;
31 import java.util.List;
32 
33 class DisplayWindowPolicyControllerHelper {
34     private static final String TAG = "DisplayWindowPolicyControllerHelper";
35 
36     private final DisplayContent mDisplayContent;
37 
38     /**
39      * The policy controller of the windows that can be displayed on the virtual display.
40      *
41      * @see DisplayWindowPolicyController
42      */
43     @Nullable
44     private DisplayWindowPolicyController mDisplayWindowPolicyController;
45 
46     /**
47      * The top non-finishing activity of this display.
48      */
49     private ActivityRecord mTopRunningActivity = null;
50 
51     /**
52      * All the uids of non-finishing activity on this display.
53      * @see DisplayWindowPolicyController#onRunningAppsChanged(ArraySet)
54      */
55     private ArraySet<Integer> mRunningUid = new ArraySet<>();
56 
DisplayWindowPolicyControllerHelper(DisplayContent displayContent)57     DisplayWindowPolicyControllerHelper(DisplayContent displayContent) {
58         mDisplayContent = displayContent;
59         mDisplayWindowPolicyController = mDisplayContent.mWmService.mDisplayManagerInternal
60                 .getDisplayWindowPolicyController(mDisplayContent.mDisplayId);
61     }
62 
63     /**
64      * Return {@code true} if there is DisplayWindowPolicyController.
65      */
hasController()66     public boolean hasController() {
67         return mDisplayWindowPolicyController != null;
68     }
69 
70     /**
71      * @see DisplayWindowPolicyController#canContainActivities(List, int)
72      */
canContainActivities(@onNull List<ActivityInfo> activities, @WindowConfiguration.WindowingMode int windowingMode)73     public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
74             @WindowConfiguration.WindowingMode int windowingMode) {
75         if (mDisplayWindowPolicyController == null) {
76             for (int i = activities.size() - 1; i >= 0; i--) {
77                 final ActivityInfo aInfo = activities.get(i);
78                 if (aInfo.requiredDisplayCategory != null) {
79                     Slog.e(TAG,
80                             String.format("Activity with requiredDisplayCategory='%s' cannot be"
81                                             + " displayed on display %d because that display does"
82                                             + " not have a matching category",
83                                     aInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
84                     return false;
85                 }
86             }
87             return true;
88         }
89         return mDisplayWindowPolicyController.canContainActivities(activities, windowingMode);
90     }
91 
92     /**
93      * @see DisplayWindowPolicyController#canActivityBeLaunched(ActivityInfo, int, int, boolean)
94      */
canActivityBeLaunched(ActivityInfo activityInfo, Intent intent, @WindowConfiguration.WindowingMode int windowingMode, int launchingFromDisplayId, boolean isNewTask)95     public boolean canActivityBeLaunched(ActivityInfo activityInfo,
96             Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
97             int launchingFromDisplayId, boolean isNewTask) {
98         if (mDisplayWindowPolicyController == null) {
99             if (activityInfo.requiredDisplayCategory != null) {
100                 Slog.e(TAG,
101                         String.format("Activity with requiredDisplayCategory='%s' cannot be"
102                                 + " launched on display %d because that display does"
103                                 + " not have a matching category",
104                                 activityInfo.requiredDisplayCategory, mDisplayContent.mDisplayId));
105                 return false;
106             }
107             return true;
108         }
109         return mDisplayWindowPolicyController.canActivityBeLaunched(activityInfo, intent,
110             windowingMode, launchingFromDisplayId, isNewTask);
111     }
112 
113     /**
114      * @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int)
115      */
keepActivityOnWindowFlagsChanged(ActivityInfo aInfo, int flagChanges, int privateFlagChanges, int flagValues, int privateFlagValues)116     boolean keepActivityOnWindowFlagsChanged(ActivityInfo aInfo, int flagChanges,
117             int privateFlagChanges, int flagValues, int privateFlagValues) {
118         if (mDisplayWindowPolicyController == null) {
119             return true;
120         }
121 
122         if (!mDisplayWindowPolicyController.isInterestedWindowFlags(
123                 flagChanges, privateFlagChanges)) {
124             return true;
125         }
126 
127         return mDisplayWindowPolicyController.keepActivityOnWindowFlagsChanged(
128                 aInfo, flagValues, privateFlagValues);
129     }
130 
131     /** Update the top activity and the uids of non-finishing activity */
onRunningActivityChanged()132     void onRunningActivityChanged() {
133         if (mDisplayWindowPolicyController == null) {
134             return;
135         }
136 
137         // Update top activity.
138         ActivityRecord topActivity = mDisplayContent.getTopActivity(false /* includeFinishing */,
139                 true /* includeOverlays */);
140         if (topActivity != mTopRunningActivity) {
141             mTopRunningActivity = topActivity;
142             if (topActivity == null) {
143                 mDisplayWindowPolicyController.onTopActivityChanged(null, Process.INVALID_UID,
144                         UserHandle.USER_NULL);
145             } else {
146                 mDisplayWindowPolicyController.onTopActivityChanged(
147                         topActivity.info.getComponentName(), topActivity.info.applicationInfo.uid,
148                         topActivity.mUserId);
149             }
150         }
151 
152         // Update running uid.
153         final boolean[] notifyChanged = {false};
154         ArraySet<Integer> runningUids = new ArraySet<>();
155         mDisplayContent.forAllActivities((r) -> {
156             if (!r.finishing) {
157                 notifyChanged[0] |= runningUids.add(r.getUid());
158             }
159         });
160 
161         // We need to compare the size because if it is the following case, we can't know the
162         // existence of 3 in the forAllActivities() loop.
163         // Old set: 1,2,3
164         // New set: 1,2
165         if (notifyChanged[0] || (mRunningUid.size() != runningUids.size())) {
166             mRunningUid = runningUids;
167             mDisplayWindowPolicyController.onRunningAppsChanged(runningUids);
168         }
169     }
170 
171     /**
172      * @see DisplayWindowPolicyController#isWindowingModeSupported(int)
173      */
isWindowingModeSupported( @indowConfiguration.WindowingMode int windowingMode)174     public final boolean isWindowingModeSupported(
175             @WindowConfiguration.WindowingMode int windowingMode) {
176         if (mDisplayWindowPolicyController == null) {
177             return true;
178         }
179         return mDisplayWindowPolicyController.isWindowingModeSupported(windowingMode);
180     }
181 
182     /**
183      * @see DisplayWindowPolicyController#canShowTasksInHostDeviceRecents()
184      */
canShowTasksInHostDeviceRecents()185     public final boolean canShowTasksInHostDeviceRecents() {
186         if (mDisplayWindowPolicyController == null) {
187             return true;
188         }
189         return mDisplayWindowPolicyController.canShowTasksInHostDeviceRecents();
190     }
191 
192     /**
193      * @see DisplayWindowPolicyController#isEnteringPipAllowed(int)
194      */
isEnteringPipAllowed(int uid)195     public final boolean isEnteringPipAllowed(int uid) {
196         if (mDisplayWindowPolicyController == null) {
197             return true;
198         }
199         return mDisplayWindowPolicyController.isEnteringPipAllowed(uid);
200     }
201 
202 
dump(String prefix, PrintWriter pw)203     void dump(String prefix, PrintWriter pw) {
204         if (mDisplayWindowPolicyController != null) {
205             pw.println();
206             mDisplayWindowPolicyController.dump(prefix, pw);
207         }
208     }
209 }
210