• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include <log/log.h>
24 
25 #include <utils/Errors.h>
26 
27 #include "AsyncCallRecorder.h"
28 #include "Scheduler/EventThread.h"
29 
30 using namespace std::chrono_literals;
31 using namespace std::placeholders;
32 
33 using testing::_;
34 using testing::Invoke;
35 
36 namespace android {
37 namespace {
38 
39 constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = 111;
40 constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID = 222;
41 constexpr PhysicalDisplayId DISPLAY_ID_64BIT = 0xabcd12349876fedcULL;
42 
43 class MockVSyncSource : public VSyncSource {
44 public:
45     MOCK_METHOD1(setVSyncEnabled, void(bool));
46     MOCK_METHOD1(setCallback, void(VSyncSource::Callback*));
47     MOCK_METHOD1(setPhaseOffset, void(nsecs_t));
48     MOCK_METHOD1(pauseVsyncCallback, void(bool));
49 };
50 
51 } // namespace
52 
53 class EventThreadTest : public testing::Test {
54 protected:
55     class MockEventThreadConnection : public EventThreadConnection {
56     public:
MockEventThreadConnection(android::impl::EventThread * eventThread,ResyncCallback && resyncCallback)57         MockEventThreadConnection(android::impl::EventThread* eventThread,
58                                   ResyncCallback&& resyncCallback)
59               : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
60         MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
61     };
62 
63     using ConnectionEventRecorder =
64             AsyncCallRecorderWithCannedReturn<status_t (*)(const DisplayEventReceiver::Event&)>;
65 
66     EventThreadTest();
67     ~EventThreadTest() override;
68 
69     void createThread();
70     sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder);
71 
72     void expectVSyncSetEnabledCallReceived(bool expectedState);
73     void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset);
74     VSyncSource::Callback* expectVSyncSetCallbackCallReceived();
75     void expectInterceptCallReceived(nsecs_t expectedTimestamp);
76     void expectVsyncEventReceivedByConnection(const char* name,
77                                               ConnectionEventRecorder& connectionEventRecorder,
78                                               nsecs_t expectedTimestamp, unsigned expectedCount);
79     void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
80     void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
81                                                 bool expectedConnected);
82     void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
83                                                       int32_t expectedConfigId);
84 
85     AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
86     AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
87     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
88     AsyncCallRecorder<void (*)()> mResyncCallRecorder;
89     AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
90     ConnectionEventRecorder mConnectionEventCallRecorder{0};
91 
92     MockVSyncSource mVSyncSource;
93     VSyncSource::Callback* mCallback = nullptr;
94     std::unique_ptr<android::impl::EventThread> mThread;
95     sp<MockEventThreadConnection> mConnection;
96 };
97 
EventThreadTest()98 EventThreadTest::EventThreadTest() {
99     const ::testing::TestInfo* const test_info =
100             ::testing::UnitTest::GetInstance()->current_test_info();
101     ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
102 
103     EXPECT_CALL(mVSyncSource, setVSyncEnabled(_))
104             .WillRepeatedly(Invoke(mVSyncSetEnabledCallRecorder.getInvocable()));
105 
106     EXPECT_CALL(mVSyncSource, setCallback(_))
107             .WillRepeatedly(Invoke(mVSyncSetCallbackCallRecorder.getInvocable()));
108 
109     EXPECT_CALL(mVSyncSource, setPhaseOffset(_))
110             .WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable()));
111 
112     createThread();
113     mConnection = createConnection(mConnectionEventCallRecorder);
114 
115     // A display must be connected for VSYNC events to be delivered.
116     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
117     expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true);
118 }
119 
~EventThreadTest()120 EventThreadTest::~EventThreadTest() {
121     const ::testing::TestInfo* const test_info =
122             ::testing::UnitTest::GetInstance()->current_test_info();
123     ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
124 
125     // EventThread should unregister itself as VSyncSource callback.
126     EXPECT_TRUE(!mVSyncSetCallbackCallRecorder.waitForUnexpectedCall().has_value());
127 }
128 
createThread()129 void EventThreadTest::createThread() {
130     mThread =
131             std::make_unique<android::impl::EventThread>(&mVSyncSource,
132                                                          mInterceptVSyncCallRecorder.getInvocable(),
133                                                          "unit-test-event-thread");
134 
135     // EventThread should register itself as VSyncSource callback.
136     mCallback = expectVSyncSetCallbackCallReceived();
137     ASSERT_TRUE(mCallback);
138 }
139 
createConnection(ConnectionEventRecorder & recorder)140 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
141         ConnectionEventRecorder& recorder) {
142     sp<MockEventThreadConnection> connection =
143             new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
144     EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
145     return connection;
146 }
147 
expectVSyncSetEnabledCallReceived(bool expectedState)148 void EventThreadTest::expectVSyncSetEnabledCallReceived(bool expectedState) {
149     auto args = mVSyncSetEnabledCallRecorder.waitForCall();
150     ASSERT_TRUE(args.has_value());
151     EXPECT_EQ(expectedState, std::get<0>(args.value()));
152 }
153 
expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset)154 void EventThreadTest::expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset) {
155     auto args = mVSyncSetPhaseOffsetCallRecorder.waitForCall();
156     ASSERT_TRUE(args.has_value());
157     EXPECT_EQ(expectedPhaseOffset, std::get<0>(args.value()));
158 }
159 
expectVSyncSetCallbackCallReceived()160 VSyncSource::Callback* EventThreadTest::expectVSyncSetCallbackCallReceived() {
161     auto callbackSet = mVSyncSetCallbackCallRecorder.waitForCall();
162     return callbackSet.has_value() ? std::get<0>(callbackSet.value()) : nullptr;
163 }
164 
expectInterceptCallReceived(nsecs_t expectedTimestamp)165 void EventThreadTest::expectInterceptCallReceived(nsecs_t expectedTimestamp) {
166     auto args = mInterceptVSyncCallRecorder.waitForCall();
167     ASSERT_TRUE(args.has_value());
168     EXPECT_EQ(expectedTimestamp, std::get<0>(args.value()));
169 }
170 
expectVsyncEventReceivedByConnection(const char * name,ConnectionEventRecorder & connectionEventRecorder,nsecs_t expectedTimestamp,unsigned expectedCount)171 void EventThreadTest::expectVsyncEventReceivedByConnection(
172         const char* name, ConnectionEventRecorder& connectionEventRecorder,
173         nsecs_t expectedTimestamp, unsigned expectedCount) {
174     auto args = connectionEventRecorder.waitForCall();
175     ASSERT_TRUE(args.has_value()) << name << " did not receive an event for timestamp "
176                                   << expectedTimestamp;
177     const auto& event = std::get<0>(args.value());
178     EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_VSYNC, event.header.type)
179             << name << " did not get the correct event for timestamp " << expectedTimestamp;
180     EXPECT_EQ(expectedTimestamp, event.header.timestamp)
181             << name << " did not get the expected timestamp for timestamp " << expectedTimestamp;
182     EXPECT_EQ(expectedCount, event.vsync.count)
183             << name << " did not get the expected count for timestamp " << expectedTimestamp;
184 }
185 
expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp,unsigned expectedCount)186 void EventThreadTest::expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp,
187                                                            unsigned expectedCount) {
188     expectVsyncEventReceivedByConnection("mConnectionEventCallRecorder",
189                                          mConnectionEventCallRecorder, expectedTimestamp,
190                                          expectedCount);
191 }
192 
expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,bool expectedConnected)193 void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
194                                                              bool expectedConnected) {
195     auto args = mConnectionEventCallRecorder.waitForCall();
196     ASSERT_TRUE(args.has_value());
197     const auto& event = std::get<0>(args.value());
198     EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type);
199     EXPECT_EQ(expectedDisplayId, event.header.displayId);
200     EXPECT_EQ(expectedConnected, event.hotplug.connected);
201 }
202 
expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,int32_t expectedConfigId)203 void EventThreadTest::expectConfigChangedEventReceivedByConnection(
204         PhysicalDisplayId expectedDisplayId, int32_t expectedConfigId) {
205     auto args = mConnectionEventCallRecorder.waitForCall();
206     ASSERT_TRUE(args.has_value());
207     const auto& event = std::get<0>(args.value());
208     EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, event.header.type);
209     EXPECT_EQ(expectedDisplayId, event.header.displayId);
210     EXPECT_EQ(expectedConfigId, event.config.configId);
211 }
212 
213 namespace {
214 
215 /* ------------------------------------------------------------------------
216  * Test cases
217  */
218 
TEST_F(EventThreadTest,canCreateAndDestroyThreadWithNoEventsSent)219 TEST_F(EventThreadTest, canCreateAndDestroyThreadWithNoEventsSent) {
220     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
221     EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
222     EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value());
223     EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value());
224     EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value());
225     EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value());
226 }
227 
TEST_F(EventThreadTest,vsyncRequestIsIgnoredIfDisplayIsDisconnected)228 TEST_F(EventThreadTest, vsyncRequestIsIgnoredIfDisplayIsDisconnected) {
229     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
230     expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
231 
232     // Signal that we want the next vsync event to be posted to the connection.
233     mThread->requestNextVsync(mConnection);
234 
235     // EventThread should not enable vsync callbacks.
236     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
237 }
238 
TEST_F(EventThreadTest,requestNextVsyncPostsASingleVSyncEventToTheConnection)239 TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
240     // Signal that we want the next vsync event to be posted to the connection
241     mThread->requestNextVsync(mConnection);
242 
243     // EventThread should immediately request a resync.
244     EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
245 
246     // EventThread should enable vsync callbacks.
247     expectVSyncSetEnabledCallReceived(true);
248 
249     // Use the received callback to signal a first vsync event.
250     // The interceptor should receive the event, as well as the connection.
251     mCallback->onVSyncEvent(123);
252     expectInterceptCallReceived(123);
253     expectVsyncEventReceivedByConnection(123, 1u);
254 
255     // Use the received callback to signal a second vsync event.
256     // The interceptor should receive the event, but the the connection should
257     // not as it was only interested in the first.
258     mCallback->onVSyncEvent(456);
259     expectInterceptCallReceived(456);
260     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
261 
262     // EventThread should also detect that at this point that it does not need
263     // any more vsync events, and should disable their generation.
264     expectVSyncSetEnabledCallReceived(false);
265 }
266 
TEST_F(EventThreadTest,setVsyncRateZeroPostsNoVSyncEventsToThatConnection)267 TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
268     // Create a first connection, register it, and request a vsync rate of zero.
269     ConnectionEventRecorder firstConnectionEventRecorder{0};
270     sp<MockEventThreadConnection> firstConnection = createConnection(firstConnectionEventRecorder);
271     mThread->setVsyncRate(0, firstConnection);
272 
273     // By itself, this should not enable vsync events
274     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
275     EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
276 
277     // However if there is another connection which wants events at a nonzero rate.....
278     ConnectionEventRecorder secondConnectionEventRecorder{0};
279     sp<MockEventThreadConnection> secondConnection =
280             createConnection(secondConnectionEventRecorder);
281     mThread->setVsyncRate(1, secondConnection);
282 
283     // EventThread should enable vsync callbacks.
284     expectVSyncSetEnabledCallReceived(true);
285 
286     // Send a vsync event. EventThread should then make a call to the
287     // interceptor, and the second connection. The first connection should not
288     // get the event.
289     mCallback->onVSyncEvent(123);
290     expectInterceptCallReceived(123);
291     EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value());
292     expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123,
293                                          1u);
294 }
295 
TEST_F(EventThreadTest,setVsyncRateOnePostsAllEventsToThatConnection)296 TEST_F(EventThreadTest, setVsyncRateOnePostsAllEventsToThatConnection) {
297     mThread->setVsyncRate(1, mConnection);
298 
299     // EventThread should enable vsync callbacks.
300     expectVSyncSetEnabledCallReceived(true);
301 
302     // Send a vsync event. EventThread should then make a call to the
303     // interceptor, and the connection.
304     mCallback->onVSyncEvent(123);
305     expectInterceptCallReceived(123);
306     expectVsyncEventReceivedByConnection(123, 1u);
307 
308     // A second event should go to the same places.
309     mCallback->onVSyncEvent(456);
310     expectInterceptCallReceived(456);
311     expectVsyncEventReceivedByConnection(456, 2u);
312 
313     // A third event should go to the same places.
314     mCallback->onVSyncEvent(789);
315     expectInterceptCallReceived(789);
316     expectVsyncEventReceivedByConnection(789, 3u);
317 }
318 
TEST_F(EventThreadTest,setVsyncRateTwoPostsEveryOtherEventToThatConnection)319 TEST_F(EventThreadTest, setVsyncRateTwoPostsEveryOtherEventToThatConnection) {
320     mThread->setVsyncRate(2, mConnection);
321 
322     // EventThread should enable vsync callbacks.
323     expectVSyncSetEnabledCallReceived(true);
324 
325     // The first event will be seen by the interceptor, and not the connection.
326     mCallback->onVSyncEvent(123);
327     expectInterceptCallReceived(123);
328     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
329 
330     // The second event will be seen by the interceptor and the connection.
331     mCallback->onVSyncEvent(456);
332     expectInterceptCallReceived(456);
333     expectVsyncEventReceivedByConnection(456, 2u);
334 
335     // The third event will be seen by the interceptor, and not the connection.
336     mCallback->onVSyncEvent(789);
337     expectInterceptCallReceived(789);
338     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
339 
340     // The fourth event will be seen by the interceptor and the connection.
341     mCallback->onVSyncEvent(101112);
342     expectInterceptCallReceived(101112);
343     expectVsyncEventReceivedByConnection(101112, 4u);
344 }
345 
TEST_F(EventThreadTest,connectionsRemovedIfInstanceDestroyed)346 TEST_F(EventThreadTest, connectionsRemovedIfInstanceDestroyed) {
347     mThread->setVsyncRate(1, mConnection);
348 
349     // EventThread should enable vsync callbacks.
350     expectVSyncSetEnabledCallReceived(true);
351 
352     // Destroy the only (strong) reference to the connection.
353     mConnection = nullptr;
354 
355     // The first event will be seen by the interceptor, and not the connection.
356     mCallback->onVSyncEvent(123);
357     expectInterceptCallReceived(123);
358     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
359 
360     // EventThread should disable vsync callbacks
361     expectVSyncSetEnabledCallReceived(false);
362 }
363 
TEST_F(EventThreadTest,connectionsRemovedIfEventDeliveryError)364 TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) {
365     ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
366     sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
367     mThread->setVsyncRate(1, errorConnection);
368 
369     // EventThread should enable vsync callbacks.
370     expectVSyncSetEnabledCallReceived(true);
371 
372     // The first event will be seen by the interceptor, and by the connection,
373     // which then returns an error.
374     mCallback->onVSyncEvent(123);
375     expectInterceptCallReceived(123);
376     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
377 
378     // A subsequent event will be seen by the interceptor and not by the
379     // connection.
380     mCallback->onVSyncEvent(456);
381     expectInterceptCallReceived(456);
382     EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value());
383 
384     // EventThread should disable vsync callbacks with the second event
385     expectVSyncSetEnabledCallReceived(false);
386 }
387 
TEST_F(EventThreadTest,eventsDroppedIfNonfatalEventDeliveryError)388 TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) {
389     ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK};
390     sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
391     mThread->setVsyncRate(1, errorConnection);
392 
393     // EventThread should enable vsync callbacks.
394     expectVSyncSetEnabledCallReceived(true);
395 
396     // The first event will be seen by the interceptor, and by the connection,
397     // which then returns an non-fatal error.
398     mCallback->onVSyncEvent(123);
399     expectInterceptCallReceived(123);
400     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
401 
402     // A subsequent event will be seen by the interceptor, and by the connection,
403     // which still then returns an non-fatal error.
404     mCallback->onVSyncEvent(456);
405     expectInterceptCallReceived(456);
406     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u);
407 
408     // EventThread will not disable vsync callbacks as the errors are non-fatal.
409     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
410 }
411 
TEST_F(EventThreadTest,setPhaseOffsetForwardsToVSyncSource)412 TEST_F(EventThreadTest, setPhaseOffsetForwardsToVSyncSource) {
413     mThread->setPhaseOffset(321);
414     expectVSyncSetPhaseOffsetCallReceived(321);
415 }
416 
TEST_F(EventThreadTest,postHotplugInternalDisconnect)417 TEST_F(EventThreadTest, postHotplugInternalDisconnect) {
418     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
419     expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
420 }
421 
TEST_F(EventThreadTest,postHotplugInternalConnect)422 TEST_F(EventThreadTest, postHotplugInternalConnect) {
423     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
424     expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true);
425 }
426 
TEST_F(EventThreadTest,postHotplugExternalDisconnect)427 TEST_F(EventThreadTest, postHotplugExternalDisconnect) {
428     mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, false);
429     expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, false);
430 }
431 
TEST_F(EventThreadTest,postHotplugExternalConnect)432 TEST_F(EventThreadTest, postHotplugExternalConnect) {
433     mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, true);
434     expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, true);
435 }
436 
TEST_F(EventThreadTest,postConfigChangedPrimary)437 TEST_F(EventThreadTest, postConfigChangedPrimary) {
438     mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 7);
439     expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7);
440 }
441 
TEST_F(EventThreadTest,postConfigChangedExternal)442 TEST_F(EventThreadTest, postConfigChangedExternal) {
443     mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, 5);
444     expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5);
445 }
446 
TEST_F(EventThreadTest,postConfigChangedPrimary64bit)447 TEST_F(EventThreadTest, postConfigChangedPrimary64bit) {
448     mThread->onConfigChanged(DISPLAY_ID_64BIT, 7);
449     expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7);
450 }
451 
452 } // namespace
453 } // namespace android
454