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 <android-base/stringprintf.h>
18 #include <binder/Parcel.h>
19 #include <gui/LayerMetadata.h>
20 
21 using android::base::StringPrintf;
22 
23 namespace android {
24 
25 LayerMetadata::LayerMetadata() = default;
26 
LayerMetadata(std::unordered_map<uint32_t,std::vector<uint8_t>> map)27 LayerMetadata::LayerMetadata(std::unordered_map<uint32_t, std::vector<uint8_t>> map)
28       : mMap(std::move(map)) {}
29 
30 LayerMetadata::LayerMetadata(const LayerMetadata& other) = default;
31 
32 LayerMetadata::LayerMetadata(LayerMetadata&& other) = default;
33 
merge(const LayerMetadata & other,bool eraseEmpty)34 bool LayerMetadata::merge(const LayerMetadata& other, bool eraseEmpty) {
35     bool changed = false;
36     for (const auto& entry : other.mMap) {
37         auto it = mMap.find(entry.first);
38         if (it != mMap.cend() && it->second != entry.second) {
39             if (eraseEmpty && entry.second.empty()) {
40                 mMap.erase(it);
41             } else {
42                 it->second = entry.second;
43             }
44             changed = true;
45         } else if (it == mMap.cend() && !entry.second.empty()) {
46             mMap[entry.first] = entry.second;
47             changed = true;
48         }
49     }
50     return changed;
51 }
52 
writeToParcel(Parcel * parcel) const53 status_t LayerMetadata::writeToParcel(Parcel* parcel) const {
54     parcel->writeInt32(static_cast<int>(mMap.size()));
55     status_t status = OK;
56     for (const auto& entry : mMap) {
57         status = parcel->writeUint32(entry.first);
58         if (status != OK) {
59             break;
60         }
61         status = parcel->writeByteVector(entry.second);
62         if (status != OK) {
63             break;
64         }
65     }
66     return status;
67 }
68 
readFromParcel(const Parcel * parcel)69 status_t LayerMetadata::readFromParcel(const Parcel* parcel) {
70     int size = parcel->readInt32();
71     status_t status = OK;
72     mMap.clear();
73     for (int i = 0; i < size; ++i) {
74         uint32_t key = parcel->readUint32();
75         status = parcel->readByteVector(&mMap[key]);
76         if (status != OK) {
77             break;
78         }
79     }
80     return status;
81 }
82 
operator =(const LayerMetadata & other)83 LayerMetadata& LayerMetadata::operator=(const LayerMetadata& other) {
84     mMap = other.mMap;
85     return *this;
86 }
87 
operator =(LayerMetadata && other)88 LayerMetadata& LayerMetadata::operator=(LayerMetadata&& other) {
89     mMap = std::move(other.mMap);
90     return *this;
91 }
92 
has(uint32_t key) const93 bool LayerMetadata::has(uint32_t key) const {
94     return mMap.count(key);
95 }
96 
getInt32(uint32_t key,int32_t fallback) const97 int32_t LayerMetadata::getInt32(uint32_t key, int32_t fallback) const {
98     if (!has(key)) return fallback;
99     const std::vector<uint8_t>& data = mMap.at(key);
100     if (data.size() < sizeof(uint32_t)) return fallback;
101     Parcel p;
102     p.setData(data.data(), data.size());
103     return p.readInt32();
104 }
105 
setInt32(uint32_t key,int32_t value)106 void LayerMetadata::setInt32(uint32_t key, int32_t value) {
107     std::vector<uint8_t>& data = mMap[key];
108     Parcel p;
109     p.writeInt32(value);
110     data.resize(p.dataSize());
111     memcpy(data.data(), p.data(), p.dataSize());
112 }
113 
itemToString(uint32_t key,const char * separator) const114 std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const {
115     if (!has(key)) return std::string();
116     switch (key) {
117         case METADATA_OWNER_UID:
118             return StringPrintf("ownerUID%s%d", separator, getInt32(key, 0));
119         case METADATA_WINDOW_TYPE:
120             return StringPrintf("windowType%s%d", separator, getInt32(key, 0));
121         case METADATA_TASK_ID:
122             return StringPrintf("taskId%s%d", separator, getInt32(key, 0));
123         default:
124             return StringPrintf("%d%s%dbytes", key, separator,
125                                 static_cast<int>(mMap.at(key).size()));
126     }
127 }
128 
129 } // namespace android
130