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