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 #include "MultiDisplayPipe.h"
18 #include "MultiDisplay.h"
19 #include "host-common/opengles.h"
20
21 namespace android {
22
23 static MultiDisplayPipe* sMultiDisplayPipeInstance = nullptr;
24 const uint8_t MultiDisplayPipe::ADD = 1;
25 const uint8_t MultiDisplayPipe::DEL = 2;
26 const uint8_t MultiDisplayPipe::QUERY = 3;
27 const uint8_t MultiDisplayPipe::BIND = 4;
28 const uint8_t MultiDisplayPipe::MAX_DISPLAYS = 10;
29
MultiDisplayPipe(AndroidPipe::Service * service,PipeArgs && pipeArgs)30 MultiDisplayPipe::MultiDisplayPipe(AndroidPipe::Service* service, PipeArgs&& pipeArgs)
31 : AndroidAsyncMessagePipe(service, std::move(pipeArgs)),
32 mService(static_cast<Service*>(service)) {
33 LOG(VERBOSE) << "MultiDisplayPipe created " << this;
34 if (sMultiDisplayPipeInstance) {
35 LOG(ERROR) << "MultiDisplayPipe already created";
36 }
37 sMultiDisplayPipeInstance = this;
38 }
39
~MultiDisplayPipe()40 MultiDisplayPipe::~MultiDisplayPipe() {
41 LOG(VERBOSE) << "MultiDisplayPipe deleted self " << this;
42 sMultiDisplayPipeInstance = NULL;
43 }
44
onMessage(const std::vector<uint8_t> & data)45 void MultiDisplayPipe::onMessage(const std::vector<uint8_t>& data) {
46 uint8_t cmd = data[0];
47 switch (cmd) {
48 case QUERY: {
49 LOG(VERBOSE) << "MultiDisplayPipe recevied QUERY";
50 uint32_t w, h, dpi, flag, id;
51 int32_t startId = -1;
52 const auto ins = MultiDisplay::getInstance();
53 while (ins && ins->getNextMultiDisplay(startId, &id, nullptr, nullptr,
54 &w, &h, &dpi, &flag, nullptr)) {
55 if (id >= MultiDisplay::s_displayIdInternalBegin) {
56 // Display created by guest through rcCommand, e.g., HWC2,
57 // not by UI/config.ini/cmd, need not report
58 break;
59 }
60 std::vector<uint8_t> buf;
61 fillData(buf, id, w, h, dpi, flag, true);
62 LOG(VERBOSE) << "MultiDisplayPipe send add id " << id << " width " << w
63 << " height " << h << " dpi " << dpi << " flag " << flag;
64 send(std::move(buf));
65 startId = id;
66 }
67 break;
68 }
69 case BIND: {
70 uint32_t id = *(uint32_t*)&(data[1]);
71 uint32_t cb = *(uint32_t*)&(data[5]);
72 LOG(VERBOSE) << "MultiDisplayPipe bind display " << id << " cb " << cb;
73 const auto ins = MultiDisplay::getInstance();
74 if (ins) {
75 ins->setDisplayColorBuffer(id, cb);
76 }
77 break;
78 }
79 default:
80 LOG(WARNING) << "unexpected cmommand " << cmd;
81 }
82
83 }
84
fillData(std::vector<uint8_t> & data,uint32_t id,uint32_t w,uint32_t h,uint32_t dpi,uint32_t flag,bool add)85 void MultiDisplayPipe::fillData(std::vector<uint8_t>& data, uint32_t id, uint32_t w, uint32_t h,
86 uint32_t dpi, uint32_t flag, bool add) {
87 uint32_t input[] = {id, w, h, dpi, flag};
88 uint8_t* p = (uint8_t*)input;
89 if (add) {
90 data.push_back(ADD);
91 } else {
92 data.push_back(DEL);
93 }
94 for (int i = 0; i < sizeof(input); i++) {
95 data.push_back(p[i]);
96 }
97 }
98
onSave(base::Stream * stream)99 void MultiDisplayPipe::onSave(base::Stream* stream) {
100 AndroidAsyncMessagePipe::onSave(stream);
101 MultiDisplay* instance = MultiDisplay::getInstance();
102 if (!instance) {
103 LOG(ERROR) << "Failed to save MultiDisplay info, MultiDisplay "
104 << "not initiated";
105 return;
106 }
107 instance->onSave(stream);
108 }
109
onLoad(base::Stream * stream)110 void MultiDisplayPipe::onLoad(base::Stream* stream) {
111 AndroidAsyncMessagePipe::onLoad(stream);
112 MultiDisplay* instance = MultiDisplay::getInstance();
113 if (!instance) {
114 LOG(ERROR) << "Failed to load MultiDisplay info, MultiDisplay "
115 << "not initiated";
116 return;
117 }
118 instance->onLoad(stream);
119 }
120
getInstance()121 MultiDisplayPipe* MultiDisplayPipe::getInstance() {
122 return sMultiDisplayPipeInstance;
123 }
124 } // namespace android
125
android_init_multi_display_pipe()126 void android_init_multi_display_pipe() {
127 android::AndroidPipe::Service::add(
128 std::make_unique<android::MultiDisplayPipe::Service>("multidisplay"));
129 }
130
131