Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* Copyright 2013 Mozilla Foundation and Mozilla contributors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
16 #include "GonkDisplayICS.h"
17 #include <ui/FramebufferNativeWindow.h>
19 #include <hardware/hardware.h>
20 #include <hardware/gralloc.h>
21 #include <hardware/hwcomposer.h>
22 #include <hardware_legacy/power.h>
23 #include <cutils/log.h>
24 #include <fcntl.h>
26 #include "mozilla/FileUtils.h"
27 #include "mozilla/NullPtr.h"
28 #include "mozilla/FileUtils.h"
30 #include "BootAnimation.h"
32 using namespace android;
35 namespace {
36 static const char* kSleepFile = "/sys/power/wait_for_fb_sleep";
37 static const char* kWakeFile = "/sys/power/wait_for_fb_wake";
38 static mozilla::GonkDisplay::OnEnabledCallbackType sEnabledCallback;
39 static pthread_t sFramebufferWatchThread;
41 static void *
42 frameBufferWatcher(void *)
43 {
44 int len = 0;
45 char buf;
47 while (true) {
48 // Cannot use epoll here because kSleepFile and kWakeFile are
49 // always ready to read and blocking.
50 {
51 mozilla::ScopedClose fd(open(kSleepFile, O_RDONLY, 0));
52 do {
53 len = read(fd.get(), &buf, 1);
54 } while (len < 0 && errno == EINTR);
55 NS_WARN_IF_FALSE(len >= 0, "WAIT_FOR_FB_SLEEP failed");
56 }
57 sEnabledCallback(false);
59 {
60 mozilla::ScopedClose fd(open(kWakeFile, O_RDONLY, 0));
61 do {
62 len = read(fd.get(), &buf, 1);
63 } while (len < 0 && errno == EINTR);
64 NS_WARN_IF_FALSE(len >= 0, "WAIT_FOR_FB_WAKE failed");
65 }
66 sEnabledCallback(true);
67 }
69 return nullptr;
70 }
72 } // anonymous namespace
75 namespace mozilla {
77 static GonkDisplayICS* sGonkDisplay = nullptr;
79 static int
80 FramebufferNativeWindowCancelBufferNoop(ANativeWindow* aWindow,
81 android_native_buffer_t* aBuffer)
82 {
83 return 0;
84 }
86 GonkDisplayICS::GonkDisplayICS()
87 : mModule(nullptr)
88 , mHwc(nullptr)
89 {
90 // Some gralloc HALs need this in order to open the
91 // framebuffer device after we restart with the screen off.
92 //
93 // this *must* run BEFORE allocating the
94 // FramebufferNativeWindow.
95 set_screen_state(1);
97 // For some devices, it takes a while for the framebuffer to become
98 // usable. So we wait until the framebuffer has woken up before we
99 // try to open it.
100 {
101 char buf;
102 int len = 0;
103 ScopedClose fd(open("/sys/power/wait_for_fb_wake", O_RDONLY, 0));
104 do {
105 len = read(fd.get(), &buf, 1);
106 } while (len < 0 && errno == EINTR);
107 if (len < 0) {
108 LOGE("BootAnimation: wait_for_fb_sleep failed errno: %d", errno);
109 }
110 }
112 mFBSurface = new FramebufferNativeWindow();
114 // ICS FramebufferNativeWindow doesn't set the |cancelBuffer|
115 // function pointer.
116 // It will crash when deleting the EGL window surface.
117 if (!mFBSurface->cancelBuffer) {
118 mFBSurface->cancelBuffer = FramebufferNativeWindowCancelBufferNoop;
119 }
121 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
122 LOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
123 if (!err) {
124 err = hwc_open(mModule, &mHwc);
125 LOGE_IF(err, "%s device failed to initialize (%s)",
126 HWC_HARDWARE_COMPOSER, strerror(-err));
127 }
129 xdpi = mFBSurface->xdpi;
131 const framebuffer_device_t *fbdev = mFBSurface->getDevice();
132 surfaceformat = fbdev->format;
134 StartBootAnimation();
135 }
137 GonkDisplayICS::~GonkDisplayICS()
138 {
139 if (mHwc)
140 hwc_close(mHwc);
141 }
143 ANativeWindow*
144 GonkDisplayICS::GetNativeWindow()
145 {
146 StopBootAnimation();
147 return static_cast<ANativeWindow *>(mFBSurface.get());
148 }
150 void
151 GonkDisplayICS::SetEnabled(bool enabled)
152 {
153 set_screen_state(enabled);
154 }
156 void
157 GonkDisplayICS::OnEnabled(OnEnabledCallbackType callback)
158 {
159 if (sEnabledCallback)
160 return;
161 sEnabledCallback = callback;
163 // Watching screen on/off state by using a pthread
164 // which implicitly calls exit() when the main thread ends
165 if (pthread_create(&sFramebufferWatchThread, NULL, frameBufferWatcher, NULL)) {
166 NS_RUNTIMEABORT("Failed to create framebufferWatcherThread, aborting...");
167 }
168 }
171 void*
172 GonkDisplayICS::GetHWCDevice()
173 {
174 return mHwc;
175 }
177 void*
178 GonkDisplayICS::GetFBSurface()
179 {
180 return mFBSurface.get();
181 }
183 bool
184 GonkDisplayICS::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
185 {
186 // Should be called when composition rendering is complete for a frame.
187 // Only HWC v1.0 needs this call. ICS gonk always needs the call.
188 mFBSurface->compositionComplete();
190 if (!mHwc)
191 return eglSwapBuffers(dpy, sur);
193 mHwc->prepare(mHwc, nullptr);
194 return !mHwc->set(mHwc, dpy, sur, 0);
195 }
197 ANativeWindowBuffer*
198 GonkDisplayICS::DequeueBuffer()
199 {
200 ANativeWindow *window = static_cast<ANativeWindow *>(mFBSurface.get());
201 ANativeWindowBuffer *buf = nullptr;
202 window->dequeueBuffer(window, &buf);
203 return buf;
204 }
206 bool
207 GonkDisplayICS::QueueBuffer(ANativeWindowBuffer *buf)
208 {
209 ANativeWindow *window = static_cast<ANativeWindow *>(mFBSurface.get());
210 return !window->queueBuffer(window, buf);
211 }
213 void
214 GonkDisplayICS::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur)
215 {
216 eglSwapBuffers(dpy, sur);
217 }
219 void
220 GonkDisplayICS::SetFBReleaseFd(int fd)
221 {
222 }
224 __attribute__ ((visibility ("default")))
225 GonkDisplay*
226 GetGonkDisplay()
227 {
228 if (!sGonkDisplay)
229 sGonkDisplay = new GonkDisplayICS();
230 return sGonkDisplay;
231 }
233 } // namespace mozilla