1 /*
2  * Copyright 2020 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 "AnimationModule.h"
18 #include "MathHelp.h"
19 
20 #include <android-base/logging.h>
21 #include <algorithm>
22 
23 namespace android {
24 namespace hardware {
25 namespace automotive {
26 namespace sv {
27 namespace V1_0 {
28 namespace implementation {
29 namespace {
operator *(std::array<float,3> lvector,float scalar)30 std::array<float, 3> operator*(std::array<float, 3> lvector, float scalar) {
31     return std::array<float, 3>{
32             lvector[0] * scalar,
33             lvector[1] * scalar,
34             lvector[2] * scalar,
35     };
36 }
37 
getRationalNumber(const Range & mappedRange,float percentage)38 inline float getRationalNumber(const Range& mappedRange, float percentage) {
39     return mappedRange.start + (mappedRange.end - mappedRange.start) * percentage;
40 }
41 
getRationalNumber(const Range & mappedRange,const Range & rawRange,float rawValue)42 inline float getRationalNumber(const Range& mappedRange, const Range& rawRange, float rawValue) {
43     if (0 == rawRange.end - rawRange.start) {
44         return mappedRange.start;
45     }
46     const float percentage = (rawValue - rawRange.start) / (rawRange.end - rawRange.start);
47     return mappedRange.start + (mappedRange.end - mappedRange.start) * percentage > 1
48             ? 1
49             : percentage < 0 ? 0 : percentage;
50 }
51 
getCombinedId(const VehiclePropValue & vhalValueFloat)52 inline uint64_t getCombinedId(const VehiclePropValue& vhalValueFloat) {
53     return static_cast<uint64_t>(vhalValueFloat.prop) << 32 | vhalValueFloat.areaId;
54 }
55 
getVhalValueFloat(const VehiclePropValue & vhalValue)56 float getVhalValueFloat(const VehiclePropValue& vhalValue) {
57     int32_t type = vhalValue.prop & 0x00FF0000;
58     switch (type) {
59         case (int32_t)VehiclePropertyType::BOOLEAN:
60             return 0 == vhalValue.value.int32Values[0] ? 0.0f : 1.0f;
61         case (int32_t)VehiclePropertyType::FLOAT:
62             return vhalValue.value.floatValues[0];
63         case (int32_t)VehiclePropertyType::INT32:
64             return (float)vhalValue.value.int32Values[0];
65         case (int32_t)VehiclePropertyType::INT64:
66             return (float)vhalValue.value.int64Values[0];
67         default:
68             return 0;
69     }
70 }
71 }  // namespace
72 
AnimationModule(const std::map<std::string,CarPart> & partsMap,const std::map<std::string,CarTexture> & texturesMap,const std::vector<AnimationInfo> & animations)73 AnimationModule::AnimationModule(const std::map<std::string, CarPart>& partsMap,
74                                  const std::map<std::string, CarTexture>& texturesMap,
75                                  const std::vector<AnimationInfo>& animations) :
76       mIsCalled(false), mPartsMap(partsMap), mTexturesMap(texturesMap), mAnimations(animations) {
77     mapVhalToParts();
78     initCarPartStatus();
79 }
80 
mapVhalToParts()81 void AnimationModule::mapVhalToParts() {
82     for (const auto& animationInfo : mAnimations) {
83         auto partId = animationInfo.partId;
84         for (const auto& gammaOp : animationInfo.gammaOpsMap) {
85             if (mVhalToPartsMap.find(gammaOp.first) != mVhalToPartsMap.end()) {
86                 mVhalToPartsMap.at(gammaOp.first).insert(partId);
87             } else {
88                 mVhalToPartsMap.emplace(
89                         std::make_pair(gammaOp.first, std::set<std::string>{partId}));
90             }
91         }
92         for (const auto& textureOp : animationInfo.textureOpsMap) {
93             if (mVhalToPartsMap.find(textureOp.first) != mVhalToPartsMap.end()) {
94                 mVhalToPartsMap.at(textureOp.first).insert(partId);
95             } else {
96                 mVhalToPartsMap.emplace(
97                         std::make_pair(textureOp.first, std::set<std::string>{partId}));
98             }
99         }
100         for (const auto& rotationOp : animationInfo.rotationOpsMap) {
101             if (mVhalToPartsMap.find(rotationOp.first) != mVhalToPartsMap.end()) {
102                 mVhalToPartsMap.at(rotationOp.first).insert(partId);
103             } else {
104                 mVhalToPartsMap.emplace(
105                         std::make_pair(rotationOp.first, std::set<std::string>{partId}));
106             }
107         }
108         for (const auto& translationOp : animationInfo.translationOpsMap) {
109             if (mVhalToPartsMap.find(translationOp.first) != mVhalToPartsMap.end()) {
110                 mVhalToPartsMap.at(translationOp.first).insert(partId);
111             } else {
112                 mVhalToPartsMap.emplace(
113                         std::make_pair(translationOp.first, std::set<std::string>{partId}));
114             }
115         }
116         mPartsToAnimationMap.emplace(std::make_pair(partId, animationInfo));
117     }
118 }
119 
initCarPartStatus()120 void AnimationModule::initCarPartStatus() {
121     for (const auto& part : mPartsMap) {
122         // Get child parts list from mPartsToAnimationMap.
123         std::vector<std::string> childIds;
124         if (mPartsToAnimationMap.find(part.first) != mPartsToAnimationMap.end()) {
125             childIds = mPartsToAnimationMap.at(part.first).childIds;
126         }
127 
128         mCarPartsStatusMap.emplace(std::make_pair(part.first,
129                                                   CarPartStatus{
130                                                           .partId = part.first,
131                                                           .childIds = childIds,
132                                                           .parentModel = gMat4Identity,
133                                                           .localModel = gMat4Identity,
134                                                           .currentModel = gMat4Identity,
135                                                           .gamma = 1,
136                                                   }));
137     }
138 
139     for (const auto& eachVhalToParts : mVhalToPartsMap) {
140         for (const auto& part : eachVhalToParts.second) {
141             if (mCarPartsStatusMap.at(part).vhalProgressMap.find(eachVhalToParts.first) !=
142                 mCarPartsStatusMap.at(part).vhalProgressMap.end()) {
143                 mCarPartsStatusMap.at(part).vhalProgressMap.at(eachVhalToParts.first) = 0.0f;
144             } else {
145                 mCarPartsStatusMap.at(part).vhalProgressMap.emplace(
146                         std::make_pair(eachVhalToParts.first, 0.0f));
147             }
148             if (mCarPartsStatusMap.at(part).vhalOffMap.find(eachVhalToParts.first) !=
149                 mCarPartsStatusMap.at(part).vhalOffMap.end()) {
150                 mCarPartsStatusMap.at(part).vhalOffMap.at(eachVhalToParts.first) = true;
151             } else {
152                 mCarPartsStatusMap.at(part).vhalOffMap.emplace(
153                         std::make_pair(eachVhalToParts.first, true));
154             }
155         }
156     }
157 }
158 
159 // This implementation assumes the tree level is small. If tree level is large,
160 // we may need to traverse the tree once and process each node(part) during
161 // the reaversal.
updateChildrenParts(const std::string & partId,const Mat4x4 & parentModel)162 void AnimationModule::updateChildrenParts(const std::string& partId, const Mat4x4& parentModel) {
163     for (auto& childPart : mCarPartsStatusMap.at(partId).childIds) {
164         mCarPartsStatusMap.at(childPart).parentModel = parentModel;
165         mCarPartsStatusMap.at(childPart).currentModel =
166                 appendMat(mCarPartsStatusMap.at(childPart).localModel,
167                           mCarPartsStatusMap.at(childPart).parentModel);
168         if (mUpdatedPartsMap.find(childPart) == mUpdatedPartsMap.end()) {
169             AnimationParam animationParam(childPart);
170             animationParam.SetModelMatrix(mCarPartsStatusMap.at(childPart).currentModel);
171             mUpdatedPartsMap.emplace(std::make_pair(childPart, animationParam));
172         } else {  // existing part in the map
173             mUpdatedPartsMap.at(childPart).SetModelMatrix(
174                     mCarPartsStatusMap.at(childPart).currentModel);
175         }
176         updateChildrenParts(childPart, mCarPartsStatusMap.at(childPart).currentModel);
177     }
178 }
179 
performGammaOp(const std::string & partId,uint64_t vhalProperty,const GammaOp & gammaOp)180 void AnimationModule::performGammaOp(const std::string& partId, uint64_t vhalProperty,
181                                      const GammaOp& gammaOp) {
182     CarPartStatus& currentCarPartStatus = mCarPartsStatusMap.at(partId);
183     float& currentProgress = currentCarPartStatus.vhalProgressMap.at(vhalProperty);
184     if (currentCarPartStatus.vhalOffMap.at(vhalProperty)) {  // process off signal
185         if (currentProgress > 0) {                           // part not rest
186             if (0 == gammaOp.animationTime) {
187                 currentCarPartStatus.gamma = gammaOp.gammaRange.start;
188                 currentProgress = 0.0f;
189             } else {
190                 const float progressDelta =
191                         (mCurrentCallTime - mLastCallTime) / gammaOp.animationTime;
192                 if (progressDelta > currentProgress) {
193                     currentCarPartStatus.gamma = gammaOp.gammaRange.start;
194                     currentProgress = 0.0f;
195                 } else {
196                     currentCarPartStatus.gamma =
197                             getRationalNumber(gammaOp.gammaRange, currentProgress - progressDelta);
198                     currentProgress -= progressDelta;
199                 }
200             }
201         } else {
202             return;
203         }
204     } else {                               // regular signal process
205         if (0 == gammaOp.animationTime) {  // continuous value
206             currentCarPartStatus.gamma =
207                     getRationalNumber(gammaOp.gammaRange, gammaOp.vhalRange,
208                                       mVhalStatusMap.at(vhalProperty).vhalValueFloat);
209             currentProgress = mVhalStatusMap.at(vhalProperty).vhalValueFloat;
210         } else {  // non-continuous value
211             const float progressDelta = (mCurrentCallTime - mLastCallTime) / gammaOp.animationTime;
212             if (gammaOp.type == ADJUST_GAMMA_ONCE) {
213                 if (progressDelta + currentCarPartStatus.vhalProgressMap.at(vhalProperty) > 1) {
214                     currentCarPartStatus.gamma = gammaOp.gammaRange.end;
215                     currentProgress = 1.0f;
216                 } else {
217                     currentCarPartStatus.gamma =
218                             getRationalNumber(gammaOp.gammaRange, currentProgress + progressDelta);
219                     currentProgress += progressDelta;
220                 }
221             } else if (gammaOp.type == ADJUST_GAMMA_REPEAT) {
222                 if (progressDelta + currentCarPartStatus.vhalProgressMap.at(vhalProperty) > 1) {
223                     if (progressDelta + currentCarPartStatus.vhalProgressMap.at(vhalProperty) - 1 >
224                         1) {
225                         currentCarPartStatus.gamma =
226                                 currentCarPartStatus.vhalProgressMap.at(vhalProperty) > 0.5
227                                 ? gammaOp.gammaRange.start
228                                 : gammaOp.gammaRange.end;
229                         currentProgress =
230                                 currentCarPartStatus.vhalProgressMap.at(vhalProperty) > 0.5 ? 0.0f
231                                                                                             : 1.0f;
232                     } else {
233                         currentCarPartStatus.gamma =
234                                 getRationalNumber(gammaOp.gammaRange,
235                                                   progressDelta +
236                                                           currentCarPartStatus.vhalProgressMap.at(
237                                                                   vhalProperty) -
238                                                           1);
239                         currentProgress += progressDelta - 1;
240                     }
241                 } else {
242                     currentCarPartStatus.gamma =
243                             getRationalNumber(gammaOp.gammaRange, currentProgress + progressDelta);
244                     currentProgress += progressDelta;
245                 }
246             } else {
247                 LOG(ERROR) << "Error type of gamma op: " << gammaOp.type;
248             }
249         }
250     }
251 
252     if (mUpdatedPartsMap.find(partId) == mUpdatedPartsMap.end()) {
253         AnimationParam animationParam(partId);
254         animationParam.SetGamma(currentCarPartStatus.gamma);
255         mUpdatedPartsMap.emplace(std::make_pair(partId, animationParam));
256     } else {  // existing part in the map
257         mUpdatedPartsMap.at(partId).SetGamma(currentCarPartStatus.gamma);
258     }
259 }
260 
performTranslationOp(const std::string & partId,uint64_t vhalProperty,const TranslationOp & translationOp)261 void AnimationModule::performTranslationOp(const std::string& partId, uint64_t vhalProperty,
262                                            const TranslationOp& translationOp) {
263     CarPartStatus& currentCarPartStatus = mCarPartsStatusMap.at(partId);
264     float& currentProgress = currentCarPartStatus.vhalProgressMap.at(vhalProperty);
265     if (currentCarPartStatus.vhalOffMap.at(vhalProperty)) {  // process off signal
266         if (currentProgress > 0) {
267             // part not rest
268             if (0 == translationOp.animationTime) {
269                 currentCarPartStatus.localModel = gMat4Identity;
270                 currentCarPartStatus.currentModel = currentCarPartStatus.parentModel;
271                 currentProgress = 0.0f;
272             } else {
273                 const float progressDelta =
274                         (mCurrentCallTime - mLastCallTime) / translationOp.animationTime;
275                 float translationUnit =
276                         getRationalNumber(translationOp.translationRange,
277                                           std::max(currentProgress - progressDelta, 0.0f));
278                 currentCarPartStatus.localModel =
279                         translationMatrixToMat4x4(translationOp.direction * translationUnit);
280                 currentCarPartStatus.currentModel = appendMatrix(currentCarPartStatus.localModel,
281                                                                  currentCarPartStatus.parentModel);
282                 currentProgress = std::max(currentProgress - progressDelta, 0.0f);
283             }
284         } else {
285             return;
286         }
287     } else {  // regular signal process
288         if (translationOp.type == TRANSLATION) {
289             if (0 == translationOp.animationTime) {
290                 float translationUnit =
291                         getRationalNumber(translationOp.translationRange, translationOp.vhalRange,
292                                           mVhalStatusMap.at(vhalProperty).vhalValueFloat);
293                 currentCarPartStatus.localModel =
294                         translationMatrixToMat4x4(translationOp.direction * translationUnit);
295                 currentCarPartStatus.currentModel = appendMatrix(currentCarPartStatus.localModel,
296                                                                  currentCarPartStatus.parentModel);
297                 currentProgress = mVhalStatusMap.at(vhalProperty).vhalValueFloat;
298             } else {
299                 float progressDelta =
300                         (mCurrentCallTime - mLastCallTime) / translationOp.animationTime;
301                 if (progressDelta + currentCarPartStatus.vhalProgressMap.at(vhalProperty) > 1) {
302                     float translationUnit = translationOp.translationRange.end;
303 
304                     currentCarPartStatus.localModel =
305                             translationMatrixToMat4x4(translationOp.direction * translationUnit);
306                     currentCarPartStatus.currentModel =
307                             appendMatrix(currentCarPartStatus.localModel,
308                                          currentCarPartStatus.parentModel);
309                     currentProgress = 1.0f;
310                 } else {
311                     float translationUnit = getRationalNumber(translationOp.translationRange,
312                                                               progressDelta + currentProgress);
313                     currentCarPartStatus.localModel =
314                             translationMatrixToMat4x4(translationOp.direction * translationUnit);
315                     currentCarPartStatus.currentModel =
316                             appendMatrix(currentCarPartStatus.localModel,
317                                          currentCarPartStatus.parentModel);
318                     currentProgress += progressDelta;
319                 }
320             }
321         } else {
322             LOG(ERROR) << "Error type of translation op: " << translationOp.type;
323         }
324     }
325     if (mUpdatedPartsMap.find(partId) == mUpdatedPartsMap.end()) {
326         AnimationParam animationParam(partId);
327         animationParam.SetModelMatrix(currentCarPartStatus.currentModel);
328         mUpdatedPartsMap.emplace(std::make_pair(partId, animationParam));
329     } else {  // existing part in the map
330         mUpdatedPartsMap.at(partId).SetModelMatrix(currentCarPartStatus.currentModel);
331     }
332     updateChildrenParts(partId, currentCarPartStatus.currentModel);
333 }
334 
performRotationOp(const std::string & partId,uint64_t vhalProperty,const RotationOp & rotationOp)335 void AnimationModule::performRotationOp(const std::string& partId, uint64_t vhalProperty,
336                                         const RotationOp& rotationOp) {
337     CarPartStatus& currentCarPartStatus = mCarPartsStatusMap.at(partId);
338     float& currentProgress = currentCarPartStatus.vhalProgressMap.at(vhalProperty);
339     if (currentCarPartStatus.vhalOffMap.at(vhalProperty)) {
340         // process off signal
341         if (currentProgress > 0) {  // part not rest
342             if (0 == rotationOp.animationTime) {
343                 currentCarPartStatus.localModel = gMat4Identity;
344                 currentCarPartStatus.currentModel = currentCarPartStatus.parentModel;
345                 currentProgress = 0.0f;
346             } else {
347                 const float progressDelta =
348                         (mCurrentCallTime - mLastCallTime) / rotationOp.animationTime;
349                 if (progressDelta > currentProgress) {
350                     currentCarPartStatus.localModel = gMat4Identity;
351                     currentCarPartStatus.currentModel = currentCarPartStatus.parentModel;
352                     currentProgress = 0.0f;
353                 } else {
354                     float anlgeInDegree = getRationalNumber(rotationOp.rotationRange,
355                                                             currentProgress - progressDelta);
356                     currentCarPartStatus.localModel =
357                             rotationAboutPoint(anlgeInDegree, rotationOp.axis.rotationPoint,
358                                                rotationOp.axis.axisVector);
359                     currentCarPartStatus.currentModel =
360                             appendMatrix(currentCarPartStatus.localModel,
361                                          currentCarPartStatus.parentModel);
362                     currentProgress -= progressDelta;
363                 }
364             }
365         } else {
366             return;
367         }
368     } else {  // regular signal process
369         if (rotationOp.type == ROTATION_ANGLE) {
370             if (0 == rotationOp.animationTime) {
371                 float angleInDegree =
372                         getRationalNumber(rotationOp.rotationRange, rotationOp.vhalRange,
373                                           mVhalStatusMap.at(vhalProperty).vhalValueFloat);
374                 currentCarPartStatus.localModel =
375                         rotationAboutPoint(angleInDegree, rotationOp.axis.rotationPoint,
376                                            rotationOp.axis.axisVector);
377                 currentCarPartStatus.currentModel = appendMatrix(currentCarPartStatus.localModel,
378                                                                  currentCarPartStatus.parentModel);
379                 currentProgress = mVhalStatusMap.at(vhalProperty).vhalValueFloat;
380             } else {
381                 float progressDelta = (mCurrentCallTime - mLastCallTime) / rotationOp.animationTime;
382                 if (progressDelta + currentProgress > 1) {
383                     float angleInDegree = rotationOp.rotationRange.end;
384                     currentCarPartStatus.localModel =
385                             rotationAboutPoint(angleInDegree, rotationOp.axis.rotationPoint,
386                                                rotationOp.axis.axisVector);
387                     currentCarPartStatus.currentModel =
388                             appendMatrix(currentCarPartStatus.localModel,
389                                          currentCarPartStatus.parentModel);
390                     currentProgress = 1.0f;
391                 } else {
392                     float anlgeInDegree = getRationalNumber(rotationOp.rotationRange,
393                                                             currentProgress + progressDelta);
394                     currentCarPartStatus.localModel =
395                             rotationAboutPoint(anlgeInDegree, rotationOp.axis.rotationPoint,
396                                                rotationOp.axis.axisVector);
397                     currentCarPartStatus.currentModel =
398                             appendMatrix(currentCarPartStatus.localModel,
399                                          currentCarPartStatus.parentModel);
400                     currentProgress += progressDelta;
401                 }
402             }
403         } else if (rotationOp.type == ROTATION_SPEED) {
404             float angleDelta = (mCurrentCallTime - mLastCallTime) *
405                     getRationalNumber(rotationOp.rotationRange, rotationOp.vhalRange,
406                                       mVhalStatusMap.at(vhalProperty)
407                                               .vhalValueFloat);  // here vhalValueFloat unit is
408                                                                  // radian/ms.
409             currentCarPartStatus.localModel =
410                     appendMat(rotationAboutPoint(angleDelta, rotationOp.axis.rotationPoint,
411                                                  rotationOp.axis.axisVector),
412                               currentCarPartStatus.localModel);
413             currentCarPartStatus.currentModel =
414                     appendMatrix(currentCarPartStatus.localModel, currentCarPartStatus.parentModel);
415             currentProgress = 1.0f;
416         } else {
417             LOG(ERROR) << "Error type of rotation op: " << rotationOp.type;
418         }
419     }
420     if (mUpdatedPartsMap.find(partId) == mUpdatedPartsMap.end()) {
421         AnimationParam animationParam(partId);
422         animationParam.SetModelMatrix(currentCarPartStatus.currentModel);
423         mUpdatedPartsMap.emplace(std::make_pair(partId, animationParam));
424     } else {  // existing part in the map
425         mUpdatedPartsMap.at(partId).SetModelMatrix(currentCarPartStatus.currentModel);
426     }
427     updateChildrenParts(partId, currentCarPartStatus.currentModel);
428 }
429 
getUpdatedAnimationParams(const std::vector<VehiclePropValue> & vehiclePropValue)430 std::vector<AnimationParam> AnimationModule::getUpdatedAnimationParams(
431         const std::vector<VehiclePropValue>& vehiclePropValue) {
432     mLastCallTime = mCurrentCallTime;
433     if (!mIsCalled) {
434         mIsCalled = true;
435         mLastCallTime = (float)elapsedRealtimeNano() / 1e6;
436     }
437 
438     // get current time
439     mCurrentCallTime = (float)elapsedRealtimeNano() / 1e6;
440 
441     // reset mUpdatedPartsMap
442     mUpdatedPartsMap.clear();
443 
444     for (const auto& vhalSignal : vehiclePropValue) {
445         // existing vhal signal
446         const uint64_t combinedId = getCombinedId(vhalSignal);
447         if (mVhalToPartsMap.find(combinedId) != mVhalToPartsMap.end()) {
448             const float valueFloat = getVhalValueFloat(vhalSignal);
449             if (mVhalStatusMap.find(combinedId) != mVhalStatusMap.end()) {
450                 mVhalStatusMap.at(combinedId).vhalValueFloat = valueFloat;
451             } else {
452                 mVhalStatusMap.emplace(std::make_pair(combinedId,
453                                                       VhalStatus{
454                                                               .vhalValueFloat = valueFloat,
455                                                       }));
456             }
457             bool offStatus = 0 == valueFloat;
458             for (const auto& eachPart : mVhalToPartsMap.at(combinedId)) {
459                 mCarPartsStatusMap.at(eachPart).vhalOffMap.at(combinedId) = offStatus;
460             }
461         }
462     }
463 
464     for (auto& vhalStatus : mVhalStatusMap) {
465         // VHAL signal not found in animation
466         uint64_t vhalProperty = vhalStatus.first;
467         if (mVhalToPartsMap.find(vhalProperty) == mVhalToPartsMap.end()) {
468             LOG(WARNING) << "VHAL " << vhalProperty << " not processed.";
469         } else {  // VHAL signal found
470             const auto& partsSet = mVhalToPartsMap.at(vhalProperty);
471             for (const auto& partId : partsSet) {
472                 const auto& animationInfo = mPartsToAnimationMap.at(partId);
473                 if (animationInfo.gammaOpsMap.find(vhalProperty) !=
474                     animationInfo.gammaOpsMap.end()) {
475                     LOG(INFO) << "Processing VHAL " << vhalProperty << " for gamma op.";
476                     // TODO(b/158244276): add priority check.
477                     for (const auto& gammaOp : animationInfo.gammaOpsMap.at(vhalProperty)) {
478                         performGammaOp(partId, vhalProperty, gammaOp);
479                     }
480                 }
481                 if (animationInfo.textureOpsMap.find(vhalProperty) !=
482                     animationInfo.textureOpsMap.end()) {
483                     LOG(INFO) << "Processing VHAL " << vhalProperty << " for texture op.";
484                     LOG(INFO) << "Texture op currently not supported. Skipped.";
485                     // TODO(b158244721): do texture op.
486                 }
487                 if (animationInfo.rotationOpsMap.find(vhalProperty) !=
488                     animationInfo.rotationOpsMap.end()) {
489                     LOG(INFO) << "Processing VHAL " << vhalProperty << " for rotation op.";
490                     for (const auto& rotationOp : animationInfo.rotationOpsMap.at(vhalProperty)) {
491                         performRotationOp(partId, vhalProperty, rotationOp);
492                     }
493                 }
494                 if (animationInfo.translationOpsMap.find(vhalProperty) !=
495                     animationInfo.translationOpsMap.end()) {
496                     LOG(INFO) << "Processing VHAL " << vhalProperty << " for translation op.";
497                     for (const auto& translationOp :
498                          animationInfo.translationOpsMap.at(vhalProperty)) {
499                         performTranslationOp(partId, vhalProperty, translationOp);
500                     }
501                 }
502             }
503         }
504     }
505 
506     std::vector<AnimationParam> output;
507     for (auto& updatedPart : mUpdatedPartsMap) {
508         output.push_back(updatedPart.second);
509     }
510     return output;
511 }
512 
513 }  // namespace implementation
514 }  // namespace V1_0
515 }  // namespace sv
516 }  // namespace automotive
517 }  // namespace hardware
518 }  // namespace android
519