widget/gonk/libdisplay/GonkDisplayICS.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

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

mercurial