1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "transaction/rs_transaction_data.h"
17
18 #include "command/rs_command.h"
19 #include "command/rs_command_factory.h"
20 #include "platform/common/rs_log.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 namespace {
25 static constexpr size_t PARCEL_MAX_CPACITY = 2000 * 1024; // upper bound of parcel capacity
26 static constexpr size_t PARCEL_SPLIT_THRESHOLD = 1800 * 1024; // should be < PARCEL_MAX_CPACITY
27 }
28
Unmarshalling(Parcel & parcel)29 RSTransactionData* RSTransactionData::Unmarshalling(Parcel& parcel)
30 {
31 auto transactionData = new RSTransactionData();
32 if (transactionData->UnmarshallingCommand(parcel)) {
33 return transactionData;
34 }
35 ROSEN_LOGE("RSTransactionData Unmarshalling Failed");
36 delete transactionData;
37 return nullptr;
38 }
39
Marshalling(Parcel & parcel) const40 bool RSTransactionData::Marshalling(Parcel& parcel) const
41 {
42 bool success = true;
43 parcel.SetMaxCapacity(PARCEL_MAX_CPACITY);
44 // to correct actual marshaled command size later, record its position in parcel
45 size_t recordPosition = parcel.GetWritePosition();
46 success = success && parcel.WriteInt32(static_cast<int32_t>(payload_.size()));
47 size_t marshaledSize = 0;
48 while (marshallingIndex_ < payload_.size()) {
49 auto& [nodeId, followType, command] = payload_[marshallingIndex_];
50 success = success && parcel.WriteUint64(nodeId);
51 success = success && parcel.WriteUint8(static_cast<uint8_t>(followType));
52 success = success && command->Marshalling(parcel);
53 if (!success) {
54 ROSEN_LOGE("failed RSTransactionData::Marshalling type:%s", command->PrintType().c_str());
55 return false;
56 }
57 ++marshallingIndex_;
58 ++marshaledSize;
59 if (parcel.GetDataSize() > PARCEL_SPLIT_THRESHOLD) {
60 break;
61 }
62 }
63 if (marshaledSize < payload_.size()) {
64 // correct command size recorded in Parcel
65 *reinterpret_cast<int32_t*>(parcel.GetData() + recordPosition) = static_cast<int32_t>(marshaledSize);
66 ROSEN_LOGW("RSTransactionData::Marshalling data split to several parcels"
67 ", marshaledSize:%zu, marshallingIndex_:%zu, total count:%zu"
68 ", parcel size:%zu, threshold:%zu",
69 marshaledSize, marshallingIndex_, payload_.size(), parcel.GetDataSize(), PARCEL_SPLIT_THRESHOLD);
70 }
71 success = success && parcel.WriteUint64(timestamp_);
72 success = success && parcel.WriteInt32(pid_);
73 success = success && parcel.WriteUint64(index_);
74 success = success && parcel.WriteBool(isUniRender_);
75 return success;
76 }
77
Process(RSContext & context)78 void RSTransactionData::Process(RSContext& context)
79 {
80 for (auto& [nodeId, followType, command] : payload_) {
81 if (command != nullptr) {
82 command->Process(context);
83 }
84 }
85 }
86
Clear()87 void RSTransactionData::Clear()
88 {
89 payload_.clear();
90 timestamp_ = 0;
91 }
92
AddCommand(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)93 void RSTransactionData::AddCommand(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
94 {
95 payload_.emplace_back(nodeId, followType, std::move(command));
96 }
97
AddCommand(std::unique_ptr<RSCommand> && command,NodeId nodeId,FollowType followType)98 void RSTransactionData::AddCommand(std::unique_ptr<RSCommand>&& command, NodeId nodeId, FollowType followType)
99 {
100 payload_.emplace_back(nodeId, followType, std::move(command));
101 }
102
UnmarshallingCommand(Parcel & parcel)103 bool RSTransactionData::UnmarshallingCommand(Parcel& parcel)
104 {
105 Clear();
106
107 int commandSize = 0;
108 if (!parcel.ReadInt32(commandSize)) {
109 ROSEN_LOGE("RSTransactionData::UnmarshallingCommand cannot read commandSize");
110 return false;
111 }
112 uint8_t followType = 0;
113 NodeId nodeId = 0;
114 uint16_t commandType = 0;
115 uint16_t commandSubType = 0;
116
117 for (int i = 0; i < commandSize; i++) {
118 if (!parcel.ReadUint64(nodeId)) {
119 ROSEN_LOGE("RSTransactionData::UnmarshallingCommand cannot read nodeId");
120 return false;
121 }
122 if (!parcel.ReadUint8(followType)) {
123 ROSEN_LOGE("RSTransactionData::UnmarshallingCommand cannot read followType");
124 return false;
125 }
126
127 if (!(parcel.ReadUint16(commandType) && parcel.ReadUint16(commandSubType))) {
128 return false;
129 }
130 auto func = RSCommandFactory::Instance().GetUnmarshallingFunc(commandType, commandSubType);
131 if (func == nullptr) {
132 return false;
133 }
134 auto command = (*func)(parcel);
135 if (command == nullptr) {
136 ROSEN_LOGE("failed RSTransactionData::UnmarshallingCommand, type=%d subtype=%d", commandType,
137 commandSubType);
138 return false;
139 }
140 payload_.emplace_back(nodeId, static_cast<FollowType>(followType), std::move(command));
141 }
142 int32_t pid;
143 return parcel.ReadUint64(timestamp_) && parcel.ReadInt32(pid) && ({pid_ = pid; true;}) &&
144 parcel.ReadUint64(index_) && parcel.ReadBool(isUniRender_);
145 }
146
147
148 } // namespace Rosen
149 } // namespace OHOS
150