| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "MultiDisplayPipe.h" |
| #include "MultiDisplay.h" |
| #include "android/opengles.h" |
| |
| namespace android { |
| |
| static MultiDisplayPipe* sMultiDisplayPipeInstance = nullptr; |
| const uint8_t MultiDisplayPipe::ADD = 1; |
| const uint8_t MultiDisplayPipe::DEL = 2; |
| const uint8_t MultiDisplayPipe::QUERY = 3; |
| const uint8_t MultiDisplayPipe::BIND = 4; |
| const uint8_t MultiDisplayPipe::MAX_DISPLAYS = 10; |
| |
| MultiDisplayPipe::MultiDisplayPipe(AndroidPipe::Service* service, PipeArgs&& pipeArgs) |
| : AndroidAsyncMessagePipe(service, std::move(pipeArgs)), |
| mService(static_cast<Service*>(service)) { |
| LOG(VERBOSE) << "MultiDisplayPipe created " << this; |
| if (sMultiDisplayPipeInstance) { |
| LOG(ERROR) << "MultiDisplayPipe already created"; |
| } |
| sMultiDisplayPipeInstance = this; |
| } |
| |
| MultiDisplayPipe::~MultiDisplayPipe() { |
| LOG(VERBOSE) << "MultiDisplayPipe deleted self " << this; |
| sMultiDisplayPipeInstance = NULL; |
| } |
| |
| void MultiDisplayPipe::onMessage(const std::vector<uint8_t>& data) { |
| uint8_t cmd = data[0]; |
| switch (cmd) { |
| case QUERY: { |
| LOG(VERBOSE) << "MultiDisplayPipe recevied QUERY"; |
| uint32_t w, h, dpi, flag, id; |
| int32_t startId = -1; |
| const auto ins = MultiDisplay::getInstance(); |
| while (ins && ins->getNextMultiDisplay(startId, &id, nullptr, nullptr, |
| &w, &h, &dpi, &flag, nullptr)) { |
| if (id >= MultiDisplay::s_displayIdInternalBegin) { |
| // Display created by guest through rcCommand, e.g., HWC2, |
| // not by UI/config.ini/cmd, need not report |
| break; |
| } |
| std::vector<uint8_t> buf; |
| fillData(buf, id, w, h, dpi, flag, true); |
| LOG(VERBOSE) << "MultiDisplayPipe send add id " << id << " width " << w |
| << " height " << h << " dpi " << dpi << " flag " << flag; |
| send(std::move(buf)); |
| startId = id; |
| } |
| break; |
| } |
| case BIND: { |
| uint32_t id = *(uint32_t*)&(data[1]); |
| uint32_t cb = *(uint32_t*)&(data[5]); |
| LOG(VERBOSE) << "MultiDisplayPipe bind display " << id << " cb " << cb; |
| const auto ins = MultiDisplay::getInstance(); |
| if (ins) { |
| ins->setDisplayColorBuffer(id, cb); |
| } |
| break; |
| } |
| default: |
| LOG(WARNING) << "unexpected cmommand " << cmd; |
| } |
| |
| } |
| |
| void MultiDisplayPipe::fillData(std::vector<uint8_t>& data, uint32_t id, uint32_t w, uint32_t h, |
| uint32_t dpi, uint32_t flag, bool add) { |
| uint32_t input[] = {id, w, h, dpi, flag}; |
| uint8_t* p = (uint8_t*)input; |
| if (add) { |
| data.push_back(ADD); |
| } else { |
| data.push_back(DEL); |
| } |
| for (int i = 0; i < sizeof(input); i++) { |
| data.push_back(p[i]); |
| } |
| } |
| |
| void MultiDisplayPipe::onSave(base::Stream* stream) { |
| AndroidAsyncMessagePipe::onSave(stream); |
| MultiDisplay* instance = MultiDisplay::getInstance(); |
| if (!instance) { |
| LOG(ERROR) << "Failed to save MultiDisplay info, MultiDisplay " |
| << "not initiated"; |
| return; |
| } |
| instance->onSave(stream); |
| } |
| |
| void MultiDisplayPipe::onLoad(base::Stream* stream) { |
| AndroidAsyncMessagePipe::onLoad(stream); |
| MultiDisplay* instance = MultiDisplay::getInstance(); |
| if (!instance) { |
| LOG(ERROR) << "Failed to load MultiDisplay info, MultiDisplay " |
| << "not initiated"; |
| return; |
| } |
| instance->onLoad(stream); |
| } |
| |
| MultiDisplayPipe* MultiDisplayPipe::getInstance() { |
| return sMultiDisplayPipeInstance; |
| } |
| } // namespace android |
| |
| void android_init_multi_display_pipe() { |
| android::AndroidPipe::Service::add( |
| std::make_unique<android::MultiDisplayPipe::Service>("multidisplay")); |
| } |
| |