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