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 #include <inttypes.h>
21 
22 #include "android/view/LayerMetadataKey.h"
23 
24 using android::base::StringPrintf;
25 
26 namespace android::gui {
27 
28 LayerMetadata::LayerMetadata() = default;
29 
LayerMetadata(std::unordered_map<uint32_t,std::vector<uint8_t>> map)30 LayerMetadata::LayerMetadata(std::unordered_map<uint32_t, std::vector<uint8_t>> map)
31       : mMap(std::move(map)) {}
32 
33 LayerMetadata::LayerMetadata(const LayerMetadata& other) = default;
34 
35 LayerMetadata::LayerMetadata(LayerMetadata&& other) = default;
36 
merge(const LayerMetadata & other,bool eraseEmpty)37 bool LayerMetadata::merge(const LayerMetadata& other, bool eraseEmpty) {
38     bool changed = false;
39     for (const auto& entry : other.mMap) {
40         auto it = mMap.find(entry.first);
41         if (it != mMap.cend() && it->second != entry.second) {
42             if (eraseEmpty && entry.second.empty()) {
43                 mMap.erase(it);
44             } else {
45                 it->second = entry.second;
46             }
47             changed = true;
48         } else if (it == mMap.cend() && !entry.second.empty()) {
49             mMap[entry.first] = entry.second;
50             changed = true;
51         }
52     }
53     return changed;
54 }
55 
writeToParcel(Parcel * parcel) const56 status_t LayerMetadata::writeToParcel(Parcel* parcel) const {
57     parcel->writeInt32(static_cast<int>(mMap.size()));
58     status_t status = OK;
59     for (const auto& entry : mMap) {
60         status = parcel->writeUint32(entry.first);
61         if (status != OK) {
62             break;
63         }
64         status = parcel->writeByteVector(entry.second);
65         if (status != OK) {
66             break;
67         }
68     }
69     return status;
70 }
71 
readFromParcel(const Parcel * parcel)72 status_t LayerMetadata::readFromParcel(const Parcel* parcel) {
73     int size = parcel->readInt32();
74     status_t status = OK;
75     mMap.clear();
76     for (int i = 0; i < size; ++i) {
77         uint32_t key = parcel->readUint32();
78         status = parcel->readByteVector(&mMap[key]);
79         if (status != OK) {
80             break;
81         }
82     }
83     return status;
84 }
85 
operator =(const LayerMetadata & other)86 LayerMetadata& LayerMetadata::operator=(const LayerMetadata& other) {
87     mMap = other.mMap;
88     return *this;
89 }
90 
operator =(LayerMetadata && other)91 LayerMetadata& LayerMetadata::operator=(LayerMetadata&& other) {
92     mMap = std::move(other.mMap);
93     return *this;
94 }
95 
has(uint32_t key) const96 bool LayerMetadata::has(uint32_t key) const {
97     return mMap.count(key);
98 }
99 
getInt32(uint32_t key,int32_t fallback) const100 int32_t LayerMetadata::getInt32(uint32_t key, int32_t fallback) const {
101     if (!has(key)) return fallback;
102     const std::vector<uint8_t>& data = mMap.at(key);
103 
104     // TODO: should handle when not equal?
105     if (data.size() < sizeof(int32_t)) return fallback;
106 
107     int32_t result;
108     memcpy(&result, data.data(), sizeof(result));
109     return result;
110 }
111 
setInt32(uint32_t key,int32_t value)112 void LayerMetadata::setInt32(uint32_t key, int32_t value) {
113     std::vector<uint8_t>& data = mMap[key];
114     data.resize(sizeof(value));
115     memcpy(data.data(), &value, sizeof(value));
116 }
117 
getInt64(uint32_t key) const118 std::optional<int64_t> LayerMetadata::getInt64(uint32_t key) const {
119     if (!has(key)) return std::nullopt;
120     const std::vector<uint8_t>& data = mMap.at(key);
121 
122     // TODO: should handle when not equal?
123     if (data.size() < sizeof(int64_t)) return std::nullopt;
124 
125     int64_t result;
126     memcpy(&result, data.data(), sizeof(result));
127     return result;
128 }
129 
itemToString(uint32_t key,const char * separator) const130 std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const {
131     if (!has(key)) return std::string();
132     switch (static_cast<view::LayerMetadataKey>(key)) {
133         case view::LayerMetadataKey::METADATA_OWNER_UID:
134             return StringPrintf("ownerUID%s%d", separator, getInt32(key, 0));
135         case view::LayerMetadataKey::METADATA_WINDOW_TYPE:
136             return StringPrintf("windowType%s%d", separator, getInt32(key, 0));
137         case view::LayerMetadataKey::METADATA_TASK_ID:
138             return StringPrintf("taskId%s%d", separator, getInt32(key, 0));
139         case view::LayerMetadataKey::METADATA_OWNER_PID:
140             return StringPrintf("ownerPID%s%d", separator, getInt32(key, 0));
141         case view::LayerMetadataKey::METADATA_DEQUEUE_TIME:
142             return StringPrintf("dequeueTime%s%" PRId64, separator, *getInt64(key));
143         case view::LayerMetadataKey::METADATA_GAME_MODE:
144             return StringPrintf("gameMode%s%d", separator, getInt32(key, 0));
145         default:
146             return StringPrintf("%d%s%dbytes", key, separator,
147                                 static_cast<int>(mMap.at(key).size()));
148     }
149 }
150 
151 } // namespace android::gui
152