• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/logging.h>
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 
21 #include "Vibrator.h"
22 #include "mocks.h"
23 #include "types.h"
24 #include "utils.h"
25 
26 namespace aidl {
27 namespace android {
28 namespace hardware {
29 namespace vibrator {
30 
31 using ::testing::_;
32 using ::testing::AnyNumber;
33 using ::testing::AnyOf;
34 using ::testing::Assign;
35 using ::testing::Combine;
36 using ::testing::DoAll;
37 using ::testing::DoDefault;
38 using ::testing::Exactly;
39 using ::testing::ExpectationSet;
40 using ::testing::Mock;
41 using ::testing::Return;
42 using ::testing::Sequence;
43 using ::testing::SetArgPointee;
44 using ::testing::SetArgReferee;
45 using ::testing::Test;
46 using ::testing::TestParamInfo;
47 using ::testing::ValuesIn;
48 using ::testing::WithParamInterface;
49 
50 // Constants With Prescribed Values
51 
52 static const std::map<EffectTuple, EffectSequence> EFFECT_SEQUENCES{
53     {{Effect::CLICK, EffectStrength::LIGHT}, {"1 0", 2}},
54     {{Effect::CLICK, EffectStrength::MEDIUM}, {"1 0", 0}},
55     {{Effect::CLICK, EffectStrength::STRONG}, {"1 0", 0}},
56     {{Effect::TICK, EffectStrength::LIGHT}, {"2 0", 2}},
57     {{Effect::TICK, EffectStrength::MEDIUM}, {"2 0", 0}},
58     {{Effect::TICK, EffectStrength::STRONG}, {"2 0", 0}},
59     {{Effect::DOUBLE_CLICK, EffectStrength::LIGHT}, {"3 0", 2}},
60     {{Effect::DOUBLE_CLICK, EffectStrength::MEDIUM}, {"3 0", 0}},
61     {{Effect::DOUBLE_CLICK, EffectStrength::STRONG}, {"3 0", 0}},
62     {{Effect::HEAVY_CLICK, EffectStrength::LIGHT}, {"4 0", 2}},
63     {{Effect::HEAVY_CLICK, EffectStrength::MEDIUM}, {"4 0", 0}},
64     {{Effect::HEAVY_CLICK, EffectStrength::STRONG}, {"4 0", 0}},
65     {{Effect::TEXTURE_TICK, EffectStrength::LIGHT}, {"2 0", 2}},
66     {{Effect::TEXTURE_TICK, EffectStrength::MEDIUM}, {"2 0", 0}},
67     {{Effect::TEXTURE_TICK, EffectStrength::STRONG}, {"2 0", 0}},
68 };
69 
freqPeriodFormula(uint32_t in)70 static uint32_t freqPeriodFormula(uint32_t in) {
71     return 1000000000 / (24615 * in);
72 }
73 
74 template <typename... T>
75 class VibratorTestTemplate : public Test, public WithParamInterface<std::tuple<bool, T...>> {
76   public:
GetDynamicConfig(typename VibratorTestTemplate::ParamType param)77     static auto GetDynamicConfig(typename VibratorTestTemplate::ParamType param) {
78         return std::get<0>(param);
79     }
80     template <std::size_t I>
GetOtherParam(typename VibratorTestTemplate::ParamType param)81     static auto GetOtherParam(typename VibratorTestTemplate::ParamType param) {
82         return std::get<I + 1>(param);
83     }
84 
PrintParam(const TestParamInfo<typename VibratorTestTemplate::ParamType> & info)85     static auto PrintParam(const TestParamInfo<typename VibratorTestTemplate::ParamType> &info) {
86         auto dynamic = GetDynamicConfig(info.param);
87         return std::string() + (dynamic ? "Dynamic" : "Static") + "Config";
88     }
89 
MakeParam(bool dynamicConfig,T...others)90     static auto MakeParam(bool dynamicConfig, T... others) {
91         return std::make_tuple(dynamicConfig, others...);
92     }
93 
SetUp()94     void SetUp() override {
95         std::unique_ptr<MockApi> mockapi;
96         std::unique_ptr<MockCal> mockcal;
97 
98         mCloseLoopThreshold = std::rand();
99         // ensure close-loop test is possible
100         if (mCloseLoopThreshold == UINT32_MAX) {
101             mCloseLoopThreshold--;
102         }
103 
104         mShortLraPeriod = std::rand();
105         if (getDynamicConfig()) {
106             mLongFrequencyShift = std::rand();
107             mLongLraPeriod =
108                 freqPeriodFormula(freqPeriodFormula(mShortLraPeriod) - mLongFrequencyShift);
109             mShortVoltageMax = std::rand();
110             mLongVoltageMax = std::rand();
111         }
112 
113         mEffectDurations[Effect::CLICK] = std::rand();
114         mEffectDurations[Effect::TICK] = std::rand();
115         mEffectDurations[Effect::DOUBLE_CLICK] = std::rand();
116         mEffectDurations[Effect::HEAVY_CLICK] = std::rand();
117         mEffectDurations[Effect::TEXTURE_TICK] = mEffectDurations[Effect::TICK];
118 
119         createMock(&mockapi, &mockcal);
120         createVibrator(std::move(mockapi), std::move(mockcal));
121     }
122 
TearDown()123     void TearDown() override { deleteVibrator(); }
124 
125   protected:
getDynamicConfig() const126     auto getDynamicConfig() const { return GetDynamicConfig(VibratorTestTemplate::GetParam()); }
127 
createMock(std::unique_ptr<MockApi> * mockapi,std::unique_ptr<MockCal> * mockcal)128     void createMock(std::unique_ptr<MockApi> *mockapi, std::unique_ptr<MockCal> *mockcal) {
129         *mockapi = std::make_unique<MockApi>();
130         *mockcal = std::make_unique<MockCal>();
131 
132         mMockApi = mockapi->get();
133         mMockCal = mockcal->get();
134 
135         ON_CALL(*mMockApi, destructor()).WillByDefault(Assign(&mMockApi, nullptr));
136         ON_CALL(*mMockApi, setOlLraPeriod(_)).WillByDefault(Return(true));
137         ON_CALL(*mMockApi, setActivate(_)).WillByDefault(Return(true));
138         ON_CALL(*mMockApi, setDuration(_)).WillByDefault(Return(true));
139         ON_CALL(*mMockApi, setMode(_)).WillByDefault(Return(true));
140         ON_CALL(*mMockApi, setCtrlLoop(_)).WillByDefault(Return(true));
141         ON_CALL(*mMockApi, setLraWaveShape(_)).WillByDefault(Return(true));
142         ON_CALL(*mMockApi, setOdClamp(_)).WillByDefault(Return(true));
143 
144         ON_CALL(*mMockCal, destructor()).WillByDefault(Assign(&mMockCal, nullptr));
145         ON_CALL(*mMockCal, getLraPeriod(_))
146             .WillByDefault(DoAll(SetArgPointee<0>(mShortLraPeriod), Return(true)));
147         ON_CALL(*mMockCal, getCloseLoopThreshold(_))
148             .WillByDefault(DoAll(SetArgPointee<0>(mCloseLoopThreshold), Return(true)));
149         ON_CALL(*mMockCal, getDynamicConfig(_))
150             .WillByDefault(DoAll(SetArgPointee<0>(getDynamicConfig()), Return(true)));
151 
152         if (getDynamicConfig()) {
153             ON_CALL(*mMockCal, getLongFrequencyShift(_))
154                 .WillByDefault(DoAll(SetArgPointee<0>(mLongFrequencyShift), Return(true)));
155             ON_CALL(*mMockCal, getShortVoltageMax(_))
156                 .WillByDefault(DoAll(SetArgPointee<0>(mShortVoltageMax), Return(true)));
157             ON_CALL(*mMockCal, getLongVoltageMax(_))
158                 .WillByDefault(DoAll(SetArgPointee<0>(mLongVoltageMax), Return(true)));
159         }
160 
161         ON_CALL(*mMockCal, getClickDuration(_))
162             .WillByDefault(DoAll(SetArgPointee<0>(mEffectDurations[Effect::CLICK]), Return(true)));
163         ON_CALL(*mMockCal, getTickDuration(_))
164             .WillByDefault(DoAll(SetArgPointee<0>(mEffectDurations[Effect::TICK]), Return(true)));
165         ON_CALL(*mMockCal, getDoubleClickDuration(_))
166             .WillByDefault(
167                 DoAll(SetArgPointee<0>(mEffectDurations[Effect::DOUBLE_CLICK]), Return(true)));
168         ON_CALL(*mMockCal, getHeavyClickDuration(_))
169             .WillByDefault(
170                 DoAll(SetArgPointee<0>(mEffectDurations[Effect::HEAVY_CLICK]), Return(true)));
171 
172         relaxMock(false);
173     }
174 
createVibrator(std::unique_ptr<MockApi> mockapi,std::unique_ptr<MockCal> mockcal,bool relaxed=true)175     void createVibrator(std::unique_ptr<MockApi> mockapi, std::unique_ptr<MockCal> mockcal,
176                         bool relaxed = true) {
177         if (relaxed) {
178             relaxMock(true);
179         }
180         mVibrator = ndk::SharedRefBase::make<Vibrator>(std::move(mockapi), std::move(mockcal));
181         if (relaxed) {
182             relaxMock(false);
183         }
184     }
185 
deleteVibrator(bool relaxed=true)186     void deleteVibrator(bool relaxed = true) {
187         if (relaxed) {
188             relaxMock(true);
189         }
190         mVibrator.reset();
191     }
192 
relaxMock(bool relax)193     void relaxMock(bool relax) {
194         auto times = relax ? AnyNumber() : Exactly(0);
195 
196         Mock::VerifyAndClearExpectations(mMockApi);
197         Mock::VerifyAndClearExpectations(mMockCal);
198 
199         EXPECT_CALL(*mMockApi, destructor()).Times(times);
200         EXPECT_CALL(*mMockApi, setAutocal(_)).Times(times);
201         EXPECT_CALL(*mMockApi, setOlLraPeriod(_)).Times(times);
202         EXPECT_CALL(*mMockApi, setActivate(_)).Times(times);
203         EXPECT_CALL(*mMockApi, setDuration(_)).Times(times);
204         EXPECT_CALL(*mMockApi, setState(_)).Times(times);
205         EXPECT_CALL(*mMockApi, hasRtpInput()).Times(times);
206         EXPECT_CALL(*mMockApi, setRtpInput(_)).Times(times);
207         EXPECT_CALL(*mMockApi, setMode(_)).Times(times);
208         EXPECT_CALL(*mMockApi, setSequencer(_)).Times(times);
209         EXPECT_CALL(*mMockApi, setScale(_)).Times(times);
210         EXPECT_CALL(*mMockApi, setCtrlLoop(_)).Times(times);
211         EXPECT_CALL(*mMockApi, setLpTriggerEffect(_)).Times(times);
212         EXPECT_CALL(*mMockApi, setLraWaveShape(_)).Times(times);
213         EXPECT_CALL(*mMockApi, setOdClamp(_)).Times(times);
214         EXPECT_CALL(*mMockApi, debug(_)).Times(times);
215 
216         EXPECT_CALL(*mMockCal, destructor()).Times(times);
217         EXPECT_CALL(*mMockCal, getAutocal(_)).Times(times);
218         EXPECT_CALL(*mMockCal, getLraPeriod(_)).Times(times);
219         EXPECT_CALL(*mMockCal, getCloseLoopThreshold(_)).Times(times);
220         EXPECT_CALL(*mMockCal, getDynamicConfig(_)).Times(times);
221         EXPECT_CALL(*mMockCal, getLongFrequencyShift(_)).Times(times);
222         EXPECT_CALL(*mMockCal, getShortVoltageMax(_)).Times(times);
223         EXPECT_CALL(*mMockCal, getLongVoltageMax(_)).Times(times);
224         EXPECT_CALL(*mMockCal, getClickDuration(_)).Times(times);
225         EXPECT_CALL(*mMockCal, getTickDuration(_)).Times(times);
226         EXPECT_CALL(*mMockCal, getDoubleClickDuration(_)).Times(times);
227         EXPECT_CALL(*mMockCal, getHeavyClickDuration(_)).Times(times);
228         EXPECT_CALL(*mMockCal, debug(_)).Times(times);
229     }
230 
231   protected:
232     MockApi *mMockApi;
233     MockCal *mMockCal;
234     std::shared_ptr<IVibrator> mVibrator;
235 
236     EffectDuration mCloseLoopThreshold;
237     uint32_t mLongFrequencyShift;
238     uint32_t mShortLraPeriod;
239     uint32_t mLongLraPeriod;
240     uint32_t mShortVoltageMax;
241     uint32_t mLongVoltageMax;
242     std::map<Effect, EffectDuration> mEffectDurations;
243 };
244 
245 using BasicTest = VibratorTestTemplate<>;
246 
TEST_P(BasicTest,Constructor)247 TEST_P(BasicTest, Constructor) {
248     std::unique_ptr<MockApi> mockapi;
249     std::unique_ptr<MockCal> mockcal;
250     std::string autocalVal = std::to_string(std::rand()) + " " + std::to_string(std::rand()) +
251                              " " + std::to_string(std::rand());
252     Sequence autocalSeq, lraPeriodSeq;
253 
254     EXPECT_CALL(*mMockApi, destructor()).WillOnce(DoDefault());
255     EXPECT_CALL(*mMockCal, destructor()).WillOnce(DoDefault());
256 
257     deleteVibrator(false);
258 
259     createMock(&mockapi, &mockcal);
260 
261     EXPECT_CALL(*mMockApi, setState(true)).WillOnce(Return(true));
262 
263     EXPECT_CALL(*mMockCal, getAutocal(_))
264         .InSequence(autocalSeq)
265         .WillOnce(DoAll(SetArgReferee<0>(autocalVal), Return(true)));
266     EXPECT_CALL(*mMockApi, setAutocal(autocalVal)).InSequence(autocalSeq).WillOnce(DoDefault());
267 
268     EXPECT_CALL(*mMockCal, getLraPeriod(_)).InSequence(lraPeriodSeq).WillOnce(DoDefault());
269 
270     EXPECT_CALL(*mMockCal, getCloseLoopThreshold(_)).WillOnce(DoDefault());
271     EXPECT_CALL(*mMockCal, getDynamicConfig(_)).WillOnce(DoDefault());
272 
273     if (getDynamicConfig()) {
274         EXPECT_CALL(*mMockCal, getLongFrequencyShift(_)).WillOnce(DoDefault());
275         EXPECT_CALL(*mMockCal, getShortVoltageMax(_)).WillOnce(DoDefault());
276         EXPECT_CALL(*mMockCal, getLongVoltageMax(_)).WillOnce(DoDefault());
277     } else {
278         EXPECT_CALL(*mMockApi, setOlLraPeriod(mShortLraPeriod))
279             .InSequence(lraPeriodSeq)
280             .WillOnce(DoDefault());
281     }
282 
283     EXPECT_CALL(*mMockCal, getClickDuration(_)).WillOnce(DoDefault());
284     EXPECT_CALL(*mMockCal, getTickDuration(_)).WillOnce(DoDefault());
285     EXPECT_CALL(*mMockCal, getDoubleClickDuration(_)).WillOnce(DoDefault());
286     EXPECT_CALL(*mMockCal, getHeavyClickDuration(_)).WillOnce(DoDefault());
287 
288     EXPECT_CALL(*mMockApi, setLpTriggerEffect(1)).WillOnce(Return(true));
289 
290     createVibrator(std::move(mockapi), std::move(mockcal), false);
291 }
292 
TEST_P(BasicTest,on)293 TEST_P(BasicTest, on) {
294     EffectDuration duration = std::rand();
295     ExpectationSet e;
296 
297     e += EXPECT_CALL(*mMockApi, setCtrlLoop(_)).WillOnce(DoDefault());
298     e += EXPECT_CALL(*mMockApi, setMode("rtp")).WillOnce(DoDefault());
299     e += EXPECT_CALL(*mMockApi, setDuration(duration)).WillOnce(DoDefault());
300 
301     if (getDynamicConfig()) {
302         e += EXPECT_CALL(*mMockApi, setLraWaveShape(0)).WillOnce(DoDefault());
303         e += EXPECT_CALL(*mMockApi, setOdClamp(mLongVoltageMax)).WillOnce(DoDefault());
304         e += EXPECT_CALL(*mMockApi, setOlLraPeriod(mLongLraPeriod)).WillOnce(DoDefault());
305     }
306 
307     EXPECT_CALL(*mMockApi, setActivate(true)).After(e).WillOnce(DoDefault());
308 
309     EXPECT_EQ(EX_NONE, mVibrator->on(duration, nullptr).getExceptionCode());
310 }
311 
TEST_P(BasicTest,on_openLoop)312 TEST_P(BasicTest, on_openLoop) {
313     EffectDuration duration = mCloseLoopThreshold;
314 
315     relaxMock(true);
316 
317     EXPECT_CALL(*mMockApi, setCtrlLoop(true)).WillOnce(DoDefault());
318 
319     EXPECT_EQ(EX_NONE, mVibrator->on(duration, nullptr).getExceptionCode());
320 }
321 
TEST_P(BasicTest,on_closeLoop)322 TEST_P(BasicTest, on_closeLoop) {
323     EffectDuration duration = mCloseLoopThreshold + 1;
324 
325     relaxMock(true);
326 
327     EXPECT_CALL(*mMockApi, setCtrlLoop(false)).WillOnce(DoDefault());
328 
329     EXPECT_EQ(EX_NONE, mVibrator->on(duration, nullptr).getExceptionCode());
330 }
331 
TEST_P(BasicTest,off)332 TEST_P(BasicTest, off) {
333     EXPECT_CALL(*mMockApi, setActivate(false)).WillOnce(DoDefault());
334 
335     EXPECT_EQ(EX_NONE, mVibrator->off().getExceptionCode());
336 }
337 
TEST_P(BasicTest,supportsAmplitudeControl_supported)338 TEST_P(BasicTest, supportsAmplitudeControl_supported) {
339     EXPECT_CALL(*mMockApi, hasRtpInput()).WillOnce(Return(true));
340 
341     int32_t capabilities;
342     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
343     EXPECT_GT(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
344 }
345 
TEST_P(BasicTest,supportsAmplitudeControl_unsupported)346 TEST_P(BasicTest, supportsAmplitudeControl_unsupported) {
347     EXPECT_CALL(*mMockApi, hasRtpInput()).WillOnce(Return(false));
348 
349     int32_t capabilities;
350     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
351     EXPECT_EQ(capabilities & IVibrator::CAP_AMPLITUDE_CONTROL, 0);
352 }
353 
TEST_P(BasicTest,setAmplitude)354 TEST_P(BasicTest, setAmplitude) {
355     EffectAmplitude amplitude = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
356 
357     EXPECT_CALL(*mMockApi, setRtpInput(amplitudeToRtpInput(amplitude))).WillOnce(Return(true));
358 
359     EXPECT_EQ(EX_NONE, mVibrator->setAmplitude(amplitude).getExceptionCode());
360 }
361 
TEST_P(BasicTest,supportsExternalControl_unsupported)362 TEST_P(BasicTest, supportsExternalControl_unsupported) {
363     EXPECT_CALL(*mMockApi, hasRtpInput()).WillOnce(Return(false));
364 
365     int32_t capabilities;
366     EXPECT_TRUE(mVibrator->getCapabilities(&capabilities).isOk());
367     EXPECT_EQ(capabilities & IVibrator::CAP_EXTERNAL_CONTROL, 0);
368 }
369 
TEST_P(BasicTest,setExternalControl_enable)370 TEST_P(BasicTest, setExternalControl_enable) {
371     EXPECT_EQ(EX_UNSUPPORTED_OPERATION, mVibrator->setExternalControl(true).getExceptionCode());
372 }
373 
TEST_P(BasicTest,setExternalControl_disable)374 TEST_P(BasicTest, setExternalControl_disable) {
375     EXPECT_EQ(EX_UNSUPPORTED_OPERATION, mVibrator->setExternalControl(false).getExceptionCode());
376 }
377 
378 INSTANTIATE_TEST_CASE_P(VibratorTests, BasicTest,
379                         ValuesIn({BasicTest::MakeParam(false), BasicTest::MakeParam(true)}),
380                         BasicTest::PrintParam);
381 
382 class EffectsTest : public VibratorTestTemplate<EffectTuple> {
383   public:
GetEffectTuple(ParamType param)384     static auto GetEffectTuple(ParamType param) { return GetOtherParam<0>(param); }
385 
PrintParam(const TestParamInfo<ParamType> & info)386     static auto PrintParam(const TestParamInfo<ParamType> &info) {
387         auto prefix = VibratorTestTemplate::PrintParam(info);
388         auto tuple = GetEffectTuple(info.param);
389         auto effect = std::get<0>(tuple);
390         auto strength = std::get<1>(tuple);
391         return prefix + "_" + toString(effect) + "_" + toString(strength);
392     }
393 
394   protected:
getEffectTuple() const395     auto getEffectTuple() const { return GetEffectTuple(GetParam()); }
396 };
397 
TEST_P(EffectsTest,perform)398 TEST_P(EffectsTest, perform) {
399     auto tuple = getEffectTuple();
400     auto effect = std::get<0>(tuple);
401     auto strength = std::get<1>(tuple);
402     auto seqIter = EFFECT_SEQUENCES.find(tuple);
403     auto durIter = mEffectDurations.find(effect);
404     EffectDuration duration;
405 
406     if (seqIter != EFFECT_SEQUENCES.end() && durIter != mEffectDurations.end()) {
407         auto sequence = std::get<0>(seqIter->second);
408         auto scale = std::get<1>(seqIter->second);
409         ExpectationSet e;
410 
411         duration = durIter->second;
412 
413         e += EXPECT_CALL(*mMockApi, setSequencer(sequence)).WillOnce(Return(true));
414         e += EXPECT_CALL(*mMockApi, setScale(scale)).WillOnce(Return(true));
415         e += EXPECT_CALL(*mMockApi, setCtrlLoop(1)).WillOnce(DoDefault());
416         e += EXPECT_CALL(*mMockApi, setMode("waveform")).WillOnce(DoDefault());
417         e += EXPECT_CALL(*mMockApi, setDuration(duration)).WillOnce(DoDefault());
418 
419         if (getDynamicConfig()) {
420             e += EXPECT_CALL(*mMockApi, setLraWaveShape(1)).WillOnce(DoDefault());
421             e += EXPECT_CALL(*mMockApi, setOdClamp(mShortVoltageMax)).WillOnce(DoDefault());
422             e += EXPECT_CALL(*mMockApi, setOlLraPeriod(mShortLraPeriod)).WillOnce(DoDefault());
423         }
424 
425         EXPECT_CALL(*mMockApi, setActivate(true)).After(e).WillOnce(DoDefault());
426     } else {
427         duration = 0;
428     }
429 
430     int32_t lengthMs;
431     ndk::ScopedAStatus status = mVibrator->perform(effect, strength, nullptr, &lengthMs);
432     if (duration) {
433         EXPECT_EQ(EX_NONE, status.getExceptionCode());
434         EXPECT_LE(duration, lengthMs);
435     } else {
436         EXPECT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
437     }
438 }
439 
440 INSTANTIATE_TEST_CASE_P(VibratorTests, EffectsTest,
441                         Combine(ValuesIn({false, true}),
442                                 Combine(ValuesIn(ndk::enum_range<Effect>().begin(),
443                                                  ndk::enum_range<Effect>().end()),
444                                         ValuesIn(ndk::enum_range<EffectStrength>().begin(),
445                                                  ndk::enum_range<EffectStrength>().end()))),
446                         EffectsTest::PrintParam);
447 
448 }  // namespace vibrator
449 }  // namespace hardware
450 }  // namespace android
451 }  // namespace aidl
452