• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 static com.android.server.wm.ActivityStarter.Request;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.UserIdInt;
24 import android.app.ActivityOptions;
25 import android.app.ActivityTaskManager;
26 import android.content.Context;
27 import android.content.pm.ActivityInfo;
28 import android.hardware.display.DisplayManager;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.view.Display;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /**
37  * Class to control the assignment of a display for Car while launching a Activity.
38  *
39  * <p>This one controls which displays users are allowed to launch.
40  * The policy should be passed from car service through
41  * {@link com.android.internal.car.ICarServiceHelper} binder interfaces. If no policy is set,
42  * this module will not change anything for launch process.</p>
43  *
44  * <p> The policy can only affect which display passenger users can use. Current user, assumed
45  * to be a driver user, is allowed to launch any display always.</p>
46  *
47  * @hide
48  */
49 public final class CarLaunchParamsModifier implements LaunchParamsController.LaunchParamsModifier {
50 
51     private final Context mContext;
52 
53     private DisplayManager mDisplayManager;  // set only from init()
54     private ActivityTaskManagerService mAtm;  // set only from init()
55 
56     private CarLaunchParamsModifierUpdatable mUpdatable;
57 
58     // getFallbackDisplayAreasForActivity() can return the most 3 {@link TaskDisplayAreaWrapper}.
59     private final ArrayList<TaskDisplayAreaWrapper> mFallBackDisplayAreaList = new ArrayList<>(3);
60 
61     /** Constructor. Can be constructed any time. */
CarLaunchParamsModifier(Context context)62     public CarLaunchParamsModifier(Context context) {
63         // This can be very early stage. So postpone interaction with other system until init.
64         mContext = context;
65     }
66 
setUpdatable(CarLaunchParamsModifierUpdatable updatable)67     public void setUpdatable(CarLaunchParamsModifierUpdatable updatable) {
68         mUpdatable = updatable;
69     }
70 
getBuiltinInterface()71     public CarLaunchParamsModifierInterface getBuiltinInterface() {
72         return mBuiltinInterface;
73     }
74 
75     /**
76      * Initializes all internal stuffs. This should be called only after ATMS, DisplayManagerService
77      * are ready.
78      */
init()79     public void init() {
80         mAtm = (ActivityTaskManagerService) ActivityTaskManager.getService();
81         LaunchParamsController controller = mAtm.mTaskSupervisor.getLaunchParamsController();
82         controller.registerModifier(this);
83         mDisplayManager = mContext.getSystemService(DisplayManager.class);
84         mDisplayManager.registerDisplayListener(mUpdatable.getDisplayListener(),
85                 new Handler(Looper.getMainLooper()));
86     }
87 
88     /** Notifies user switching. */
handleUserStarting(@serIdInt int startingUserId)89     public void handleUserStarting(@UserIdInt int startingUserId) {
90         mUpdatable.handleUserStarting(startingUserId);
91     }
92 
93     /** Notifies user switching. */
handleCurrentUserSwitching(@serIdInt int newUserId)94     public void handleCurrentUserSwitching(@UserIdInt int newUserId) {
95         mUpdatable.handleCurrentUserSwitching(newUserId);
96     }
97 
98     /** Notifies user stopped. */
handleUserStopped(@serIdInt int stoppedUser)99     public void handleUserStopped(@UserIdInt int stoppedUser) {
100         mUpdatable.handleUserStopped(stoppedUser);
101     }
102 
103     /**
104      * Decides display to assign while an Activity is launched.
105      *
106      * <p>For current user (=driver), launching to any display is allowed as long as system
107      * allows it.</p>
108      *
109      * <p>For private display, do not change anything as private display has its own logic.</p>
110      *
111      * <p>For passenger displays, only run in allowed displays. If requested display is not
112      * allowed, change to the 1st allowed display.</p>
113      */
114     @Override
115     @Result
onCalculate(@ullable Task task, @Nullable ActivityInfo.WindowLayout layout, @Nullable ActivityRecord activity, @Nullable ActivityRecord source, ActivityOptions options, @Nullable Request request, int phase, LaunchParamsController.LaunchParams currentParams, LaunchParamsController.LaunchParams outParams)116     public int onCalculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
117             @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
118             ActivityOptions options, @Nullable Request request, int phase,
119             LaunchParamsController.LaunchParams currentParams,
120             LaunchParamsController.LaunchParams outParams) {
121         CalculateParams params = CalculateParams.create(task, layout, activity, source,
122                 options, request, phase, currentParams, outParams, mAtm.mSupportsMultiDisplay);
123         return mUpdatable.calculate(params);
124     }
125 
126     @Nullable
getDefaultTaskDisplayAreaOnDisplay(int displayId)127     private TaskDisplayAreaWrapper getDefaultTaskDisplayAreaOnDisplay(int displayId) {
128         if (displayId == Display.INVALID_DISPLAY) {
129             return null;
130         }
131         DisplayContent dc = mAtm.mRootWindowContainer.getDisplayContentOrCreate(displayId);
132         if (dc == null) {
133             return null;
134         }
135         return TaskDisplayAreaWrapper.create(dc.getDefaultTaskDisplayArea());
136     }
137 
138     /**
139      * Calculates the default {@link TaskDisplayAreaWrapper} for a task. We attempt to put
140      * the activity within the same display area if possible. The strategy is to find the display
141      * in the following order:
142      *
143      * <ol>
144      *     <li>The display area of the top activity from the launching process will be used</li>
145      *     <li>The display area of the top activity from the real launching process will be used
146      *     </li>
147      *     <li>Default display area from the associated root window container.</li>
148      * </ol>
149      * @param activityRecordWrapper the activity being started
150      * @param requestWrapper optional {@link RequestWrapper} made to start the activity record
151      * @return the list of {@link TaskDisplayAreaWrapper} to house the task
152      */
getFallbackDisplayAreasForActivity( @onNull ActivityRecordWrapper activityRecordWrapper, @Nullable RequestWrapper requestWrapper)153     private List<TaskDisplayAreaWrapper> getFallbackDisplayAreasForActivity(
154             @NonNull ActivityRecordWrapper activityRecordWrapper,
155             @Nullable RequestWrapper requestWrapper) {
156         ActivityRecord activityRecord = activityRecordWrapper.getActivityRecord();
157         Request request = requestWrapper != null ? requestWrapper.getRequest() : null;
158         mFallBackDisplayAreaList.clear();
159 
160         WindowProcessController controllerFromLaunchingRecord = mAtm.getProcessController(
161                 activityRecord.launchedFromPid, activityRecord.launchedFromUid);
162         TaskDisplayArea displayAreaForLaunchingRecord = controllerFromLaunchingRecord == null
163                 ? null : controllerFromLaunchingRecord.getTopActivityDisplayArea();
164         if (displayAreaForLaunchingRecord != null) {
165             mFallBackDisplayAreaList.add(
166                     TaskDisplayAreaWrapper.create(displayAreaForLaunchingRecord));
167         }
168 
169         WindowProcessController controllerFromProcess = mAtm.getProcessController(
170                 activityRecord.getProcessName(), activityRecord.getUid());
171         TaskDisplayArea displayAreaForRecord = controllerFromProcess == null ? null
172                 : controllerFromProcess.getTopActivityDisplayArea();
173         if (displayAreaForRecord != null) {
174             mFallBackDisplayAreaList.add(TaskDisplayAreaWrapper.create(displayAreaForRecord));
175         }
176 
177         WindowProcessController controllerFromRequest =
178                 request == null ? null : mAtm.getProcessController(request.realCallingPid,
179                         request.realCallingUid);
180         TaskDisplayArea displayAreaFromSourceProcess = controllerFromRequest == null ? null
181                 : controllerFromRequest.getTopActivityDisplayArea();
182         if (displayAreaFromSourceProcess != null) {
183             mFallBackDisplayAreaList.add(
184                     TaskDisplayAreaWrapper.create(displayAreaFromSourceProcess));
185         }
186         return mFallBackDisplayAreaList;
187     }
188 
189     @Nullable
findTaskDisplayArea(int displayId, int featureId)190     private TaskDisplayAreaWrapper findTaskDisplayArea(int displayId, int featureId) {
191         DisplayContent display = mAtm.mRootWindowContainer.getDisplayContent(displayId);
192         if (display == null) {
193             return null;
194         }
195         TaskDisplayArea tda = display.getItemFromTaskDisplayAreas(
196                 displayArea -> displayArea.mFeatureId == featureId ? displayArea : null);
197         return TaskDisplayAreaWrapper.create(tda);
198     }
199 
200     private final CarLaunchParamsModifierInterface mBuiltinInterface
201             = new CarLaunchParamsModifierInterface() {
202         @Nullable
203         @Override
204         public TaskDisplayAreaWrapper findTaskDisplayArea(int displayId, int featureId) {
205             return CarLaunchParamsModifier.this.findTaskDisplayArea(displayId, featureId);
206         }
207 
208         @Nullable
209         @Override
210         public TaskDisplayAreaWrapper getDefaultTaskDisplayAreaOnDisplay(int displayId) {
211             return CarLaunchParamsModifier.this.getDefaultTaskDisplayAreaOnDisplay(displayId);
212         }
213 
214         @NonNull
215         @Override
216         public List<TaskDisplayAreaWrapper> getFallbackDisplayAreasForActivity(
217                 @NonNull ActivityRecordWrapper activityRecord, @Nullable RequestWrapper request) {
218             return CarLaunchParamsModifier.this.getFallbackDisplayAreasForActivity(
219                     activityRecord, request);
220         }
221     };
222 }
223