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 #pragma once
18 
19 #include "aemu/base/EventNotificationSupport.h"
20 #include "aemu/base/files/Stream.h"
21 #include "aemu/base/synchronization/Lock.h"
22 #include "host-common/record_screen_agent.h"
23 #include "host-common/vm_operations.h"
24 #include "host-common/window_agent.h"
25 
26 #include <map>
27 
28 namespace android {
29 
30 struct MultiDisplayInfo {
31     int32_t pos_x;
32     int32_t pos_y;
33     uint32_t width;
34     uint32_t height;
35     uint32_t originalWidth;
36     uint32_t originalHeight;
37     uint32_t dpi;
38     uint32_t flag;
39     uint32_t cb;
40     int32_t  rotation;
41     bool     enabled;
MultiDisplayInfoMultiDisplayInfo42     MultiDisplayInfo() :
43       pos_x(0), pos_y(0), width(0), height(0), originalWidth(0),
44       originalHeight(0), dpi(0), flag(0), cb(0), rotation(0), enabled(true) {}
45     MultiDisplayInfo(int32_t x, int32_t y, uint32_t w, uint32_t h,
46                      uint32_t d, uint32_t f, bool e, uint32_t c = 0) :
pos_xMultiDisplayInfo47       pos_x(x), pos_y(y), width(w), height(h), originalWidth(w),
48       originalHeight(h), dpi(d), flag(f), rotation(0), enabled(e), cb(c) {}
49 
50 };
51 
52  enum class DisplayChange {
53     DisplayChanged = 0,
54     DisplayAdded,
55     DisplayRemoved,
56     DisplayTransactionCompleted,
57 };
58 
59 struct DisplayChangeEvent {
60     DisplayChange change;
61     uint32_t displayId;
62 };
63 
64 class MultiDisplay :  public base::EventNotificationSupport<DisplayChangeEvent> {
65 public:
66     MultiDisplay(const QAndroidEmulatorWindowAgent* const windowAgent,
67                  const QAndroidRecordScreenAgent* const recordAgent,
68                  const QAndroidVmOperations* const vmAgent,
69                  bool isGuestMode);
70     static MultiDisplay* getInstance();
isMultiDisplayEnabled()71     bool isMultiDisplayEnabled() { base::AutoLock lock(mLock); return mMultiDisplay.size() > 1; }
72     int setMultiDisplay(uint32_t id,
73                          int32_t x,
74                          int32_t y,
75                          uint32_t w,
76                          uint32_t h,
77                          uint32_t dpi,
78                          uint32_t flag,
79                          bool add);
getMultiDisplay(uint32_t id,int32_t * x,int32_t * y,uint32_t * width,uint32_t * height,uint32_t * dpi,uint32_t * flag,bool * enabled)80     bool getMultiDisplay(uint32_t id,
81                          int32_t* x,
82                          int32_t* y,
83                          uint32_t* width,
84                          uint32_t* height,
85                          uint32_t* dpi,
86                          uint32_t* flag,
87                          bool* enabled) {
88         return getMultiDisplay(id, x, y, width, height, dpi, flag, nullptr, enabled);
89     }
90     bool getNextMultiDisplay(int32_t start_id,
91                              uint32_t* id,
92                              int32_t* x,
93                              int32_t* y,
94                              uint32_t* w,
95                              uint32_t* h,
96                              uint32_t* dpi,
97                              uint32_t* flag,
98                              uint32_t* cb);
99     bool multiDisplayParamValidate(uint32_t id, uint32_t w, uint32_t h,
100                                    uint32_t dpi, uint32_t flag);
101     bool translateCoordination(uint32_t* x, uint32_t* y, uint32_t* displayId);
102     void setGpuMode(bool isGuestMode, uint32_t w, uint32_t h);
103     int createDisplay(uint32_t* displayId);
104     int setDisplayPose(uint32_t displayId,
105                        int32_t x,
106                        int32_t y,
107                        uint32_t w,
108                        uint32_t h,
109                        uint32_t dpi,
110                        uint32_t flag);
111     int destroyDisplay(uint32_t displayId);
112     int getDisplayPose(uint32_t displayId,
113                        int32_t* x,
114                        int32_t* y,
115                        uint32_t* w,
116                        uint32_t* h);
117     int getDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer);
118     int getColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId);
119     int setDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer);
120     void getCombinedDisplaySize(uint32_t* w, uint32_t* h);
121     bool isMultiDisplayWindow();
122     bool isDisplayPipeReady();
123     bool startDisplayPipe();
124     bool isPixelFold();
125     void loadConfig();
126     void onSave(base::Stream* stream);
127     void onLoad(base::Stream* stream);
128     void performRotation(int rot);
129 
130     bool notifyDisplayChanges();
131     bool isOrientationSupported();
132 
133     // 0 for default Android display
134     // 1-5 for Emulator UI
135     // 6-10 for developer from rcControl
136     static constexpr uint32_t s_displayIdInternalBegin = 6;
137     static constexpr uint32_t s_maxNumMultiDisplay = 11;
138     static constexpr uint32_t s_invalidIdMultiDisplay = 0xFFFFFFAB;
139 
140 private:
141     const QAndroidEmulatorWindowAgent* mWindowAgent;
142     const QAndroidRecordScreenAgent* mRecordAgent;
143     const QAndroidVmOperations* mVmAgent;
144     bool mGuestMode;
145     int32_t  mRotation { 0 };
146     std::map<uint32_t, MultiDisplayInfo> mMultiDisplay;
147     android::base::Lock mLock;
148 
149     void performRotationLocked(int rot);
150     void recomputeLayoutLocked();
151     void recomputeStackedLayoutLocked();
152     void getCombinedDisplaySizeLocked(uint32_t* w, uint32_t* h);
153     bool getMultiDisplay(uint32_t id,
154                          int32_t* x,
155                          int32_t* y,
156                          uint32_t* width,
157                          uint32_t* height,
158                          uint32_t* dpi,
159                          uint32_t* flag,
160                          uint32_t* cb,
161                          bool* enabled);
162     int getNumberActiveMultiDisplaysLocked();
163 
164     std::map<uint32_t, MultiDisplayInfo> parseConfig();
165     bool hotPlugDisplayEnabled();
166 };
167 } // namespace android
168 
169 void android_init_multi_display(const QAndroidEmulatorWindowAgent* const windowAgent,
170                                 const QAndroidRecordScreenAgent* const recordAgent,
171                                 const QAndroidVmOperations* const vmAgent,
172                                 bool isGUestMode = false);
173