Bug 742226 - Refactor battery updater using the uevent poller. r=cjones
authorCervantes Yu <cyu@mozilla.com>
Wed, 11 Apr 2012 15:59:00 +0800
changeset 94881 dd28759eba7b1d75772c2ea69326347b5be4ec4c
parent 94880 8f0af0cf88a945230cadf0d707b002a286ebaabd
child 94882 c7d6c4305f9397296eb0e97e99b6ea9aa8c9dc6b
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs742226
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 742226 - Refactor battery updater using the uevent poller. r=cjones
hal/gonk/GonkHal.cpp
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -1,32 +1,35 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "base/message_loop.h"
 #include "hardware_legacy/uevent.h"
 #include "Hal.h"
 #include "HalImpl.h"
 #include "mozilla/dom/battery/Constants.h"
 #include "mozilla/FileUtils.h"
 #include "nsAlgorithm.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Services.h"
 #include "mozilla/FileUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIRunnable.h"
 #include "nsIThread.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
+#include "nsXULAppAPI.h"
 #include "hardware/lights.h"
 #include "hardware/hardware.h"
 #include "hardware_legacy/vibrator.h"
+#include "UeventPoller.h"
 #include <stdio.h>
 #include <math.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <time.h>
 #include <sys/syscall.h>
 #include <cutils/properties.h>
 #include "mozilla/dom/network/Constants.h"
@@ -191,80 +194,84 @@ public:
   {
     hal::BatteryInformation info;
     hal_impl::GetCurrentBatteryInformation(&info);
     hal::NotifyBatteryChange(info);
     return NS_OK;
   }
 };
 
-class UEventWatcher : public nsRunnable {
+} // anonymous namespace
+
+class BatteryObserver : public IUeventObserver,
+                        public RefCounted<BatteryObserver>
+{
 public:
-  UEventWatcher()
-    : mUpdater(new BatteryUpdater())
-    , mRunning(false)
+  BatteryObserver()
+    :mUpdater(new BatteryUpdater())
   {
   }
 
-  NS_IMETHOD Run()
+  virtual void Notify(const NetlinkEvent &aEvent)
   {
-    while (mRunning) {
-      char buf[1024];
-      int count = uevent_next_event(buf, sizeof(buf) - 1);
-      if (!count) {
-        NS_WARNING("uevent_next_event() returned 0!");
-        continue;
-      }
-
-      buf[sizeof(buf) - 1] = 0;
-      if (strstr(buf, "battery"))
-        NS_DispatchToMainThread(mUpdater);
+    // this will run on IO thread
+    NetlinkEvent *event = const_cast<NetlinkEvent*>(&aEvent);
+    const char *subsystem = event->getSubsystem();
+    // e.g. DEVPATH=/devices/platform/sec-battery/power_supply/battery
+    const char *devpath = event->findParam("DEVPATH");
+    if (strcmp(subsystem, "power_supply") == 0 &&
+        strstr(devpath, "battery")) {
+      // aEvent will be valid only in this method.
+      NS_DispatchToMainThread(mUpdater);
     }
-    return NS_OK;
   }
 
-  bool mRunning;
-
 private:
   nsRefPtr<BatteryUpdater> mUpdater;
 };
 
-} // anonymous namespace
+// sBatteryObserver is owned by the IO thread. Only the IO thread may
+// create or destroy it.
+static BatteryObserver *sBatteryObserver = NULL;
 
-static bool sUEventInitialized = false;
-static UEventWatcher *sWatcher = NULL;
-static nsIThread *sWatcherThread = NULL;
+static void
+RegisterBatteryObserverIOThread()
+{
+  MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
+  MOZ_ASSERT(!sBatteryObserver);
+
+  sBatteryObserver = new BatteryObserver();
+  RegisterUeventListener(sBatteryObserver);
+}
 
 void
 EnableBatteryNotifications()
 {
-  if (!sUEventInitialized)
-    sUEventInitialized = uevent_init();
-  if (!sUEventInitialized) {
-    NS_WARNING("uevent_init() failed!");
-    return;
-  }
+  XRE_GetIOMessageLoop()->PostTask(
+      FROM_HERE,
+      NewRunnableFunction(RegisterBatteryObserverIOThread));
+}
 
-  if (!sWatcher)
-    sWatcher = new UEventWatcher();
-  NS_ADDREF(sWatcher);
+static void
+UnregisterBatteryObserverIOThread()
+{
+  MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
+  MOZ_ASSERT(sBatteryObserver);
 
-  sWatcher->mRunning = true;
-  nsresult rv = NS_NewThread(&sWatcherThread, sWatcher);
-  if (NS_FAILED(rv))
-    NS_WARNING("Failed to get new thread for uevent watching");
+  UnregisterUeventListener(sBatteryObserver);
+  delete sBatteryObserver;
+  sBatteryObserver = NULL;
 }
 
 void
 DisableBatteryNotifications()
 {
-  sWatcher->mRunning = false;
-  sWatcherThread->Shutdown();
-  NS_IF_RELEASE(sWatcherThread);
-  delete sWatcher;
+  XRE_GetIOMessageLoop()->PostTask(
+      FROM_HERE,
+      NewRunnableFunction(UnregisterBatteryObserverIOThread));
 }
 
 void
 GetCurrentBatteryInformation(hal::BatteryInformation *aBatteryInfo)
 {
   static const int BATTERY_NOT_CHARGING = 0;
   static const int BATTERY_CHARGING_USB = 1;
   static const int BATTERY_CHARGING_AC  = 2;