1 /* 2 * Copyright (C) 2020 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; 18 19 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE; 20 21 import android.app.WindowConfiguration; 22 import android.util.SparseArray; 23 import android.view.SurfaceControl; 24 import android.window.DisplayAreaAppearedInfo; 25 import android.window.DisplayAreaInfo; 26 import android.window.DisplayAreaOrganizer; 27 import android.window.WindowContainerTransaction; 28 29 import androidx.annotation.NonNull; 30 31 import com.android.internal.protolog.common.ProtoLog; 32 33 import java.io.PrintWriter; 34 import java.util.List; 35 import java.util.concurrent.Executor; 36 37 /** Display area organizer for the root display areas */ 38 public class RootDisplayAreaOrganizer extends DisplayAreaOrganizer { 39 40 private static final String TAG = RootDisplayAreaOrganizer.class.getSimpleName(); 41 42 /** {@link DisplayAreaInfo} list, which is mapped by display IDs. */ 43 private final SparseArray<DisplayAreaInfo> mDisplayAreasInfo = new SparseArray<>(); 44 /** Display area leashes, which is mapped by display IDs. */ 45 private final SparseArray<SurfaceControl> mLeashes = new SparseArray<>(); 46 RootDisplayAreaOrganizer(Executor executor)47 public RootDisplayAreaOrganizer(Executor executor) { 48 super(executor); 49 List<DisplayAreaAppearedInfo> infos = registerOrganizer(FEATURE_ROOT); 50 for (int i = infos.size() - 1; i >= 0; --i) { 51 onDisplayAreaAppeared(infos.get(i).getDisplayAreaInfo(), infos.get(i).getLeash()); 52 } 53 } 54 attachToDisplayArea(int displayId, SurfaceControl.Builder b)55 public void attachToDisplayArea(int displayId, SurfaceControl.Builder b) { 56 final SurfaceControl sc = mLeashes.get(displayId); 57 if (sc != null) { 58 b.setParent(sc); 59 } 60 } 61 62 @Override onDisplayAreaAppeared(@onNull DisplayAreaInfo displayAreaInfo, @NonNull SurfaceControl leash)63 public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo, 64 @NonNull SurfaceControl leash) { 65 if (displayAreaInfo.featureId != FEATURE_ROOT) { 66 throw new IllegalArgumentException( 67 "Unknown feature: " + displayAreaInfo.featureId 68 + "displayAreaInfo:" + displayAreaInfo); 69 } 70 71 final int displayId = displayAreaInfo.displayId; 72 if (mDisplayAreasInfo.get(displayId) != null) { 73 throw new IllegalArgumentException( 74 "Duplicate DA for displayId: " + displayId 75 + " displayAreaInfo:" + displayAreaInfo 76 + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId)); 77 } 78 79 leash.setUnreleasedWarningCallSite("RootDisplayAreaOrganizer.onDisplayAreaAppeared"); 80 mDisplayAreasInfo.put(displayId, displayAreaInfo); 81 mLeashes.put(displayId, leash); 82 } 83 84 @Override onDisplayAreaVanished(@onNull DisplayAreaInfo displayAreaInfo)85 public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) { 86 final int displayId = displayAreaInfo.displayId; 87 if (mDisplayAreasInfo.get(displayId) == null) { 88 throw new IllegalArgumentException( 89 "onDisplayAreaVanished() Unknown DA displayId: " + displayId 90 + " displayAreaInfo:" + displayAreaInfo 91 + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId)); 92 } 93 94 mDisplayAreasInfo.remove(displayId); 95 mLeashes.get(displayId).release(); 96 mLeashes.remove(displayId); 97 } 98 99 @Override onDisplayAreaInfoChanged(@onNull DisplayAreaInfo displayAreaInfo)100 public void onDisplayAreaInfoChanged(@NonNull DisplayAreaInfo displayAreaInfo) { 101 final int displayId = displayAreaInfo.displayId; 102 if (mDisplayAreasInfo.get(displayId) == null) { 103 throw new IllegalArgumentException( 104 "onDisplayAreaInfoChanged() Unknown DA displayId: " + displayId 105 + " displayAreaInfo:" + displayAreaInfo 106 + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId)); 107 } 108 109 mDisplayAreasInfo.put(displayId, displayAreaInfo); 110 } 111 112 /** 113 * Create a {@link WindowContainerTransaction} to update display windowing mode. 114 * 115 * @param displayId display id to update windowing mode for 116 * @param windowingMode target {@link WindowConfiguration.WindowingMode} 117 * @return {@link WindowContainerTransaction} with pending operation to set windowing mode 118 */ prepareWindowingModeChange(int displayId, @WindowConfiguration.WindowingMode int windowingMode)119 public WindowContainerTransaction prepareWindowingModeChange(int displayId, 120 @WindowConfiguration.WindowingMode int windowingMode) { 121 WindowContainerTransaction wct = new WindowContainerTransaction(); 122 DisplayAreaInfo displayAreaInfo = mDisplayAreasInfo.get(displayId); 123 if (displayAreaInfo == null) { 124 ProtoLog.e(WM_SHELL_DESKTOP_MODE, 125 "unable to update windowing mode for display %d display not found", displayId); 126 return wct; 127 } 128 129 ProtoLog.d(WM_SHELL_DESKTOP_MODE, 130 "setWindowingMode: displayId=%d current wmMode=%d new wmMode=%d", displayId, 131 displayAreaInfo.configuration.windowConfiguration.getWindowingMode(), 132 windowingMode); 133 134 wct.setWindowingMode(displayAreaInfo.token, windowingMode); 135 return wct; 136 } 137 dump(@onNull PrintWriter pw, String prefix)138 public void dump(@NonNull PrintWriter pw, String prefix) { 139 final String innerPrefix = prefix + " "; 140 final String childPrefix = innerPrefix + " "; 141 pw.println(prefix + this); 142 143 for (int i = 0; i < mDisplayAreasInfo.size(); i++) { 144 int displayId = mDisplayAreasInfo.keyAt(i); 145 DisplayAreaInfo displayAreaInfo = mDisplayAreasInfo.get(displayId); 146 int windowingMode = 147 displayAreaInfo.configuration.windowConfiguration.getWindowingMode(); 148 pw.println(innerPrefix + "# displayId=" + displayId + " wmMode=" + windowingMode); 149 } 150 } 151 152 @Override toString()153 public String toString() { 154 return TAG + "#" + mDisplayAreasInfo.size(); 155 } 156 157 } 158