Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2013 Mozilla Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
18 #define LOG_TAG "GonkNativeWindowClient"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20 //#define LOG_NDEBUG 0
22 #include <android/native_window.h>
24 #include <binder/Parcel.h>
26 #include <utils/Log.h>
27 #include <utils/Trace.h>
29 #include <ui/Fence.h>
31 #include "GonkNativeWindowClientKK.h"
33 namespace android {
35 GonkNativeWindowClient::GonkNativeWindowClient(
36 const sp<IGraphicBufferProducer>& bufferProducer,
37 bool controlledByApp)
38 : mGraphicBufferProducer(bufferProducer)
39 {
40 // Initialize the ANativeWindow function pointers.
41 ANativeWindow::setSwapInterval = hook_setSwapInterval;
42 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
43 ANativeWindow::cancelBuffer = hook_cancelBuffer;
44 ANativeWindow::queueBuffer = hook_queueBuffer;
45 ANativeWindow::query = hook_query;
46 ANativeWindow::perform = hook_perform;
48 ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
49 ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
50 ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
51 ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
53 const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
54 const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
56 mReqWidth = 0;
57 mReqHeight = 0;
58 mReqFormat = 0;
59 mReqUsage = 0;
60 mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
61 mCrop.clear();
62 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
63 mTransform = 0;
64 mDefaultWidth = 0;
65 mDefaultHeight = 0;
66 mUserWidth = 0;
67 mUserHeight = 0;
68 mTransformHint = 0;
69 mConsumerRunningBehind = false;
70 mConnectedToCpu = false;
71 mProducerControlledByApp = controlledByApp;
72 mSwapIntervalZero = false;
73 }
75 GonkNativeWindowClient::~GonkNativeWindowClient() {
76 if (mConnectedToCpu) {
77 GonkNativeWindowClient::disconnect(NATIVE_WINDOW_API_CPU);
78 }
79 }
81 sp<IGraphicBufferProducer> GonkNativeWindowClient::getIGraphicBufferProducer() const {
82 return mGraphicBufferProducer;
83 }
85 int GonkNativeWindowClient::hook_setSwapInterval(ANativeWindow* window, int interval) {
86 GonkNativeWindowClient* c = getSelf(window);
87 return c->setSwapInterval(interval);
88 }
90 int GonkNativeWindowClient::hook_dequeueBuffer(ANativeWindow* window,
91 ANativeWindowBuffer** buffer, int* fenceFd) {
92 GonkNativeWindowClient* c = getSelf(window);
93 return c->dequeueBuffer(buffer, fenceFd);
94 }
96 int GonkNativeWindowClient::hook_cancelBuffer(ANativeWindow* window,
97 ANativeWindowBuffer* buffer, int fenceFd) {
98 GonkNativeWindowClient* c = getSelf(window);
99 return c->cancelBuffer(buffer, fenceFd);
100 }
102 int GonkNativeWindowClient::hook_queueBuffer(ANativeWindow* window,
103 ANativeWindowBuffer* buffer, int fenceFd) {
104 GonkNativeWindowClient* c = getSelf(window);
105 return c->queueBuffer(buffer, fenceFd);
106 }
108 int GonkNativeWindowClient::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
109 ANativeWindowBuffer** buffer) {
110 GonkNativeWindowClient* c = getSelf(window);
111 ANativeWindowBuffer* buf;
112 int fenceFd = -1;
113 int result = c->dequeueBuffer(&buf, &fenceFd);
114 sp<Fence> fence(new Fence(fenceFd));
115 int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
116 if (waitResult != OK) {
117 ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
118 waitResult);
119 c->cancelBuffer(buf, -1);
120 return waitResult;
121 }
122 *buffer = buf;
123 return result;
124 }
126 int GonkNativeWindowClient::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
127 ANativeWindowBuffer* buffer) {
128 GonkNativeWindowClient* c = getSelf(window);
129 return c->cancelBuffer(buffer, -1);
130 }
132 int GonkNativeWindowClient::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
133 ANativeWindowBuffer* buffer) {
134 GonkNativeWindowClient* c = getSelf(window);
135 return c->lockBuffer_DEPRECATED(buffer);
136 }
138 int GonkNativeWindowClient::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
139 ANativeWindowBuffer* buffer) {
140 GonkNativeWindowClient* c = getSelf(window);
141 return c->queueBuffer(buffer, -1);
142 }
144 int GonkNativeWindowClient::hook_query(const ANativeWindow* window,
145 int what, int* value) {
146 const GonkNativeWindowClient* c = getSelf(window);
147 return c->query(what, value);
148 }
150 int GonkNativeWindowClient::hook_perform(ANativeWindow* window, int operation, ...) {
151 va_list args;
152 va_start(args, operation);
153 GonkNativeWindowClient* c = getSelf(window);
154 return c->perform(operation, args);
155 }
157 int GonkNativeWindowClient::setSwapInterval(int interval) {
158 ATRACE_CALL();
159 // EGL specification states:
160 // interval is silently clamped to minimum and maximum implementation
161 // dependent values before being stored.
163 if (interval < minSwapInterval)
164 interval = minSwapInterval;
166 if (interval > maxSwapInterval)
167 interval = maxSwapInterval;
169 return NO_ERROR;
170 }
172 int GonkNativeWindowClient::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
173 ATRACE_CALL();
174 ALOGV("GonkNativeWindowClient::dequeueBuffer");
175 Mutex::Autolock lock(mMutex);
176 int buf = -1;
177 int reqW = mReqWidth ? mReqWidth : mUserWidth;
178 int reqH = mReqHeight ? mReqHeight : mUserHeight;
179 sp<Fence> fence;
180 status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
181 reqW, reqH, mReqFormat, mReqUsage);
182 if (result < 0) {
183 ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
184 "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
185 result);
186 return result;
187 }
188 sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
190 // this should never happen
191 ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
193 if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
194 freeAllBuffers();
195 }
197 if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
198 result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
199 if (result != NO_ERROR) {
200 ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
201 return result;
202 }
203 }
205 if (fence->isValid()) {
206 *fenceFd = fence->dup();
207 if (*fenceFd == -1) {
208 ALOGE("dequeueBuffer: error duping fence: %d", errno);
209 // dup() should never fail; something is badly wrong. Soldier on
210 // and hope for the best; the worst that should happen is some
211 // visible corruption that lasts until the next frame.
212 }
213 } else {
214 *fenceFd = -1;
215 }
217 *buffer = gbuf.get();
218 return OK;
219 }
221 int GonkNativeWindowClient::cancelBuffer(android_native_buffer_t* buffer,
222 int fenceFd) {
223 ATRACE_CALL();
224 ALOGV("GonkNativeWindowClient::cancelBuffer");
225 Mutex::Autolock lock(mMutex);
226 int i = getSlotFromBufferLocked(buffer);
227 if (i < 0) {
228 return i;
229 }
230 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
231 mGraphicBufferProducer->cancelBuffer(i, fence);
232 return OK;
233 }
235 int GonkNativeWindowClient::getSlotFromBufferLocked(
236 android_native_buffer_t* buffer) const {
237 bool dumpedState = false;
238 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
239 if (mSlots[i].buffer != NULL &&
240 mSlots[i].buffer->handle == buffer->handle) {
241 return i;
242 }
243 }
244 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
245 return BAD_VALUE;
246 }
248 int GonkNativeWindowClient::lockBuffer_DEPRECATED(android_native_buffer_t* buffer) {
249 ALOGV("GonkNativeWindowClient::lockBuffer");
250 Mutex::Autolock lock(mMutex);
251 return OK;
252 }
254 int GonkNativeWindowClient::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
255 ATRACE_CALL();
256 ALOGV("GonkNativeWindowClient::queueBuffer");
257 Mutex::Autolock lock(mMutex);
258 int64_t timestamp;
259 bool isAutoTimestamp = false;
260 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
261 timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
262 isAutoTimestamp = true;
263 ALOGV("GonkNativeWindowClient::queueBuffer making up timestamp: %.2f ms",
264 timestamp / 1000000.f);
265 } else {
266 timestamp = mTimestamp;
267 }
268 int i = getSlotFromBufferLocked(buffer);
269 if (i < 0) {
270 return i;
271 }
274 // Make sure the crop rectangle is entirely inside the buffer.
275 Rect crop;
276 mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
278 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
279 IGraphicBufferProducer::QueueBufferOutput output;
280 IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
281 crop, mScalingMode, mTransform, mSwapIntervalZero, fence);
282 status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
283 if (err != OK) {
284 ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
285 }
286 uint32_t numPendingBuffers = 0;
287 output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
288 &numPendingBuffers);
290 mConsumerRunningBehind = (numPendingBuffers >= 2);
292 return err;
293 }
295 int GonkNativeWindowClient::query(int what, int* value) const {
296 ATRACE_CALL();
297 ALOGV("GonkNativeWindowClient::query");
298 { // scope for the lock
299 Mutex::Autolock lock(mMutex);
300 switch (what) {
301 case NATIVE_WINDOW_FORMAT:
302 if (mReqFormat) {
303 *value = mReqFormat;
304 return NO_ERROR;
305 }
306 break;
307 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
308 //sp<ISurfaceComposer> composer(
309 // ComposerService::getComposerService());
310 //if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
311 // *value = 1;
312 //} else {
313 *value = 0;
314 //}
315 return NO_ERROR;
316 }
317 case NATIVE_WINDOW_CONCRETE_TYPE:
318 *value = NATIVE_WINDOW_SURFACE;
319 return NO_ERROR;
320 case NATIVE_WINDOW_DEFAULT_WIDTH:
321 *value = mUserWidth ? mUserWidth : mDefaultWidth;
322 return NO_ERROR;
323 case NATIVE_WINDOW_DEFAULT_HEIGHT:
324 *value = mUserHeight ? mUserHeight : mDefaultHeight;
325 return NO_ERROR;
326 case NATIVE_WINDOW_TRANSFORM_HINT:
327 *value = mTransformHint;
328 return NO_ERROR;
329 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
330 status_t err = NO_ERROR;
331 if (!mConsumerRunningBehind) {
332 *value = 0;
333 } else {
334 err = mGraphicBufferProducer->query(what, value);
335 if (err == NO_ERROR) {
336 mConsumerRunningBehind = *value;
337 }
338 }
339 return err;
340 }
341 }
342 }
343 return mGraphicBufferProducer->query(what, value);
344 }
346 int GonkNativeWindowClient::perform(int operation, va_list args)
347 {
348 int res = NO_ERROR;
349 switch (operation) {
350 case NATIVE_WINDOW_CONNECT:
351 // deprecated. must return NO_ERROR.
352 break;
353 case NATIVE_WINDOW_DISCONNECT:
354 // deprecated. must return NO_ERROR.
355 break;
356 case NATIVE_WINDOW_SET_USAGE:
357 res = dispatchSetUsage(args);
358 break;
359 case NATIVE_WINDOW_SET_CROP:
360 res = dispatchSetCrop(args);
361 break;
362 case NATIVE_WINDOW_SET_BUFFER_COUNT:
363 res = dispatchSetBufferCount(args);
364 break;
365 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
366 res = dispatchSetBuffersGeometry(args);
367 break;
368 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
369 res = dispatchSetBuffersTransform(args);
370 break;
371 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
372 res = dispatchSetBuffersTimestamp(args);
373 break;
374 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
375 res = dispatchSetBuffersDimensions(args);
376 break;
377 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
378 res = dispatchSetBuffersUserDimensions(args);
379 break;
380 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
381 res = dispatchSetBuffersFormat(args);
382 break;
383 case NATIVE_WINDOW_LOCK:
384 res = dispatchLock(args);
385 break;
386 case NATIVE_WINDOW_UNLOCK_AND_POST:
387 res = dispatchUnlockAndPost(args);
388 break;
389 case NATIVE_WINDOW_SET_SCALING_MODE:
390 res = dispatchSetScalingMode(args);
391 break;
392 case NATIVE_WINDOW_API_CONNECT:
393 res = dispatchConnect(args);
394 break;
395 case NATIVE_WINDOW_API_DISCONNECT:
396 res = dispatchDisconnect(args);
397 break;
398 default:
399 res = NAME_NOT_FOUND;
400 break;
401 }
402 return res;
403 }
405 int GonkNativeWindowClient::dispatchConnect(va_list args) {
406 int api = va_arg(args, int);
407 return connect(api);
408 }
410 int GonkNativeWindowClient::dispatchDisconnect(va_list args) {
411 int api = va_arg(args, int);
412 return disconnect(api);
413 }
415 int GonkNativeWindowClient::dispatchSetUsage(va_list args) {
416 int usage = va_arg(args, int);
417 return setUsage(usage);
418 }
420 int GonkNativeWindowClient::dispatchSetCrop(va_list args) {
421 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
422 return setCrop(reinterpret_cast<Rect const*>(rect));
423 }
425 int GonkNativeWindowClient::dispatchSetBufferCount(va_list args) {
426 size_t bufferCount = va_arg(args, size_t);
427 return setBufferCount(bufferCount);
428 }
430 int GonkNativeWindowClient::dispatchSetBuffersGeometry(va_list args) {
431 int w = va_arg(args, int);
432 int h = va_arg(args, int);
433 int f = va_arg(args, int);
434 int err = setBuffersDimensions(w, h);
435 if (err != 0) {
436 return err;
437 }
438 return setBuffersFormat(f);
439 }
441 int GonkNativeWindowClient::dispatchSetBuffersDimensions(va_list args) {
442 int w = va_arg(args, int);
443 int h = va_arg(args, int);
444 return setBuffersDimensions(w, h);
445 }
447 int GonkNativeWindowClient::dispatchSetBuffersUserDimensions(va_list args) {
448 int w = va_arg(args, int);
449 int h = va_arg(args, int);
450 return setBuffersUserDimensions(w, h);
451 }
453 int GonkNativeWindowClient::dispatchSetBuffersFormat(va_list args) {
454 int f = va_arg(args, int);
455 return setBuffersFormat(f);
456 }
458 int GonkNativeWindowClient::dispatchSetScalingMode(va_list args) {
459 int m = va_arg(args, int);
460 return setScalingMode(m);
461 }
463 int GonkNativeWindowClient::dispatchSetBuffersTransform(va_list args) {
464 int transform = va_arg(args, int);
465 return setBuffersTransform(transform);
466 }
468 int GonkNativeWindowClient::dispatchSetBuffersTimestamp(va_list args) {
469 int64_t timestamp = va_arg(args, int64_t);
470 return setBuffersTimestamp(timestamp);
471 }
473 int GonkNativeWindowClient::dispatchLock(va_list args) {
474 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
475 ARect* inOutDirtyBounds = va_arg(args, ARect*);
476 return lock(outBuffer, inOutDirtyBounds);
477 }
479 int GonkNativeWindowClient::dispatchUnlockAndPost(va_list args) {
480 return unlockAndPost();
481 }
484 int GonkNativeWindowClient::connect(int api) {
485 ATRACE_CALL();
486 ALOGV("GonkNativeWindowClient::connect");
487 static sp<BBinder> sLife = new BBinder();
488 Mutex::Autolock lock(mMutex);
489 IGraphicBufferProducer::QueueBufferOutput output;
490 int err = mGraphicBufferProducer->connect(sLife, api, true, &output);
491 if (err == NO_ERROR) {
492 uint32_t numPendingBuffers = 0;
493 output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
494 &numPendingBuffers);
495 mConsumerRunningBehind = (numPendingBuffers >= 2);
496 }
497 if (!err && api == NATIVE_WINDOW_API_CPU) {
498 mConnectedToCpu = true;
499 }
500 return err;
501 }
504 int GonkNativeWindowClient::disconnect(int api) {
505 ATRACE_CALL();
506 ALOGV("GonkNativeWindowClient::disconnect");
507 Mutex::Autolock lock(mMutex);
508 freeAllBuffers();
509 int err = mGraphicBufferProducer->disconnect(api);
510 if (!err) {
511 mReqFormat = 0;
512 mReqWidth = 0;
513 mReqHeight = 0;
514 mReqUsage = 0;
515 mCrop.clear();
516 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
517 mTransform = 0;
518 if (api == NATIVE_WINDOW_API_CPU) {
519 mConnectedToCpu = false;
520 }
521 }
522 return err;
523 }
525 int GonkNativeWindowClient::setUsage(uint32_t reqUsage)
526 {
527 ALOGV("GonkNativeWindowClient::setUsage");
528 Mutex::Autolock lock(mMutex);
529 mReqUsage = reqUsage;
530 return OK;
531 }
533 int GonkNativeWindowClient::setCrop(Rect const* rect)
534 {
535 ATRACE_CALL();
537 Rect realRect;
538 if (rect == NULL || rect->isEmpty()) {
539 realRect.clear();
540 } else {
541 realRect = *rect;
542 }
544 ALOGV("GonkNativeWindowClient::setCrop rect=[%d %d %d %d]",
545 realRect.left, realRect.top, realRect.right, realRect.bottom);
547 Mutex::Autolock lock(mMutex);
548 mCrop = realRect;
549 return NO_ERROR;
550 }
552 int GonkNativeWindowClient::setBufferCount(int bufferCount)
553 {
554 ATRACE_CALL();
555 ALOGV("GonkNativeWindowClient::setBufferCount");
556 Mutex::Autolock lock(mMutex);
558 status_t err = mGraphicBufferProducer->setBufferCount(bufferCount);
559 ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
560 bufferCount, strerror(-err));
562 if (err == NO_ERROR) {
563 freeAllBuffers();
564 }
566 return err;
567 }
569 int GonkNativeWindowClient::setBuffersDimensions(int w, int h)
570 {
571 ATRACE_CALL();
572 ALOGV("GonkNativeWindowClient::setBuffersDimensions");
574 if (w<0 || h<0)
575 return BAD_VALUE;
577 if ((w && !h) || (!w && h))
578 return BAD_VALUE;
580 Mutex::Autolock lock(mMutex);
581 mReqWidth = w;
582 mReqHeight = h;
583 return NO_ERROR;
584 }
586 int GonkNativeWindowClient::setBuffersUserDimensions(int w, int h)
587 {
588 ATRACE_CALL();
589 ALOGV("GonkNativeWindowClient::setBuffersUserDimensions");
591 if (w<0 || h<0)
592 return BAD_VALUE;
594 if ((w && !h) || (!w && h))
595 return BAD_VALUE;
597 Mutex::Autolock lock(mMutex);
598 mUserWidth = w;
599 mUserHeight = h;
600 return NO_ERROR;
601 }
603 int GonkNativeWindowClient::setBuffersFormat(int format)
604 {
605 ALOGV("GonkNativeWindowClient::setBuffersFormat");
607 if (format<0)
608 return BAD_VALUE;
610 Mutex::Autolock lock(mMutex);
611 mReqFormat = format;
612 return NO_ERROR;
613 }
615 int GonkNativeWindowClient::setScalingMode(int mode)
616 {
617 ATRACE_CALL();
618 ALOGV("GonkNativeWindowClient::setScalingMode(%d)", mode);
620 switch (mode) {
621 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
622 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
623 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
624 break;
625 default:
626 ALOGE("unknown scaling mode: %d", mode);
627 return BAD_VALUE;
628 }
630 Mutex::Autolock lock(mMutex);
631 mScalingMode = mode;
632 return NO_ERROR;
633 }
635 int GonkNativeWindowClient::setBuffersTransform(int transform)
636 {
637 ATRACE_CALL();
638 ALOGV("GonkNativeWindowClient::setBuffersTransform");
639 Mutex::Autolock lock(mMutex);
640 mTransform = transform;
641 return NO_ERROR;
642 }
644 int GonkNativeWindowClient::setBuffersTimestamp(int64_t timestamp)
645 {
646 ALOGV("GonkNativeWindowClient::setBuffersTimestamp");
647 Mutex::Autolock lock(mMutex);
648 mTimestamp = timestamp;
649 return NO_ERROR;
650 }
652 void GonkNativeWindowClient::freeAllBuffers() {
653 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
654 mSlots[i].buffer = 0;
655 }
656 }
658 // ----------------------------------------------------------------------
659 // the lock/unlock APIs must be used from the same thread
661 // ----------------------------------------------------------------------------
663 status_t GonkNativeWindowClient::lock(
664 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
665 {
666 return INVALID_OPERATION;
667 }
669 status_t GonkNativeWindowClient::unlockAndPost()
670 {
671 return INVALID_OPERATION;
672 }
674 }; // namespace android