• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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