diff options
Diffstat (limited to 'hal/gonk')
-rw-r--r-- | hal/gonk/GonkDiskSpaceWatcher.cpp | 324 | ||||
-rw-r--r-- | hal/gonk/GonkHal.cpp | 2045 | ||||
-rw-r--r-- | hal/gonk/GonkSensor.cpp | 861 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsHelpers.cpp | 112 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsHelpers.h | 226 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsInterface.cpp | 494 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsInterface.h | 191 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsPollInterface.cpp | 431 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsPollInterface.h | 340 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsRegistryInterface.cpp | 213 | ||||
-rw-r--r-- | hal/gonk/GonkSensorsRegistryInterface.h | 182 | ||||
-rw-r--r-- | hal/gonk/GonkSwitch.cpp | 479 | ||||
-rw-r--r-- | hal/gonk/SensorsTypes.h | 140 | ||||
-rw-r--r-- | hal/gonk/SystemService.cpp | 131 | ||||
-rw-r--r-- | hal/gonk/UeventPoller.cpp | 312 | ||||
-rw-r--r-- | hal/gonk/UeventPoller.h | 49 | ||||
-rw-r--r-- | hal/gonk/fanotify.h | 118 | ||||
-rw-r--r-- | hal/gonk/nsIRecoveryService.idl | 39 | ||||
-rw-r--r-- | hal/gonk/tavarua.h | 484 |
19 files changed, 0 insertions, 7171 deletions
diff --git a/hal/gonk/GonkDiskSpaceWatcher.cpp b/hal/gonk/GonkDiskSpaceWatcher.cpp deleted file mode 100644 index cdc48ef89..000000000 --- a/hal/gonk/GonkDiskSpaceWatcher.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* 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 "Hal.h" -#include <sys/syscall.h> -#include <sys/vfs.h> -#include <fcntl.h> -#include <errno.h> -#include "base/message_loop.h" -#include "base/task.h" -#include "DiskSpaceWatcher.h" -#include "fanotify.h" -#include "nsIObserverService.h" -#include "nsIDiskSpaceWatcher.h" -#include "nsThreadUtils.h" -#include "nsXULAppAPI.h" -#include "mozilla/ModuleUtils.h" -#include "mozilla/Preferences.h" -#include "mozilla/Services.h" - -using namespace mozilla; - -namespace mozilla { namespace hal_impl { class GonkDiskSpaceWatcher; } } - -using namespace mozilla::hal_impl; - -namespace mozilla { -namespace hal_impl { - -// NOTE: this should be unnecessary once we no longer support ICS. -#ifndef __NR_fanotify_init -#if defined(__ARM_EABI__) -#define __NR_fanotify_init 367 -#define __NR_fanotify_mark 368 -#elif defined(__i386__) -#define __NR_fanotify_init 338 -#define __NR_fanotify_mark 339 -#else -#error "Unhandled architecture" -#endif -#endif - -// fanotify_init and fanotify_mark functions are syscalls. -// The user space bits are not part of bionic so we add them here -// as well as fanotify.h -int fanotify_init (unsigned int flags, unsigned int event_f_flags) -{ - return syscall(__NR_fanotify_init, flags, event_f_flags); -} - -// Add, remove, or modify an fanotify mark on a filesystem object. -int fanotify_mark (int fanotify_fd, unsigned int flags, - uint64_t mask, int dfd, const char *pathname) -{ - - // On 32 bits platforms we have to convert the 64 bits mask into - // two 32 bits ints. - if (sizeof(void *) == 4) { - union { - uint64_t _64; - uint32_t _32[2]; - } _mask; - _mask._64 = mask; - return syscall(__NR_fanotify_mark, fanotify_fd, flags, - _mask._32[0], _mask._32[1], dfd, pathname); - } - - return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname); -} - -class GonkDiskSpaceWatcher final : public MessageLoopForIO::Watcher -{ -public: - GonkDiskSpaceWatcher(); - ~GonkDiskSpaceWatcher() {}; - - virtual void OnFileCanReadWithoutBlocking(int aFd); - - // We should never write to the fanotify fd. - virtual void OnFileCanWriteWithoutBlocking(int aFd) - { - MOZ_CRASH("Must not write to fanotify fd"); - } - - void DoStart(); - void DoStop(); - -private: - void NotifyUpdate(); - - uint64_t mLowThreshold; - uint64_t mHighThreshold; - TimeDuration mTimeout; - TimeStamp mLastTimestamp; - uint64_t mLastFreeSpace; - uint32_t mSizeDelta; - - bool mIsDiskFull; - uint64_t mFreeSpace; - - int mFd; - MessageLoopForIO::FileDescriptorWatcher mReadWatcher; -}; - -static GonkDiskSpaceWatcher* gHalDiskSpaceWatcher = nullptr; - -#define WATCHER_PREF_LOW "disk_space_watcher.low_threshold" -#define WATCHER_PREF_HIGH "disk_space_watcher.high_threshold" -#define WATCHER_PREF_TIMEOUT "disk_space_watcher.timeout" -#define WATCHER_PREF_SIZE_DELTA "disk_space_watcher.size_delta" - -static const char kWatchedPath[] = "/data"; - -// Helper class to dispatch calls to xpcom on the main thread. -class DiskSpaceNotifier : public Runnable -{ -public: - DiskSpaceNotifier(const bool aIsDiskFull, const uint64_t aFreeSpace) : - mIsDiskFull(aIsDiskFull), - mFreeSpace(aFreeSpace) {} - - NS_IMETHOD Run() override - { - MOZ_ASSERT(NS_IsMainThread()); - DiskSpaceWatcher::UpdateState(mIsDiskFull, mFreeSpace); - return NS_OK; - } - -private: - bool mIsDiskFull; - uint64_t mFreeSpace; -}; - -// Helper runnable to delete the watcher on the main thread. -class DiskSpaceCleaner : public Runnable -{ -public: - NS_IMETHOD Run() override - { - MOZ_ASSERT(NS_IsMainThread()); - if (gHalDiskSpaceWatcher) { - delete gHalDiskSpaceWatcher; - gHalDiskSpaceWatcher = nullptr; - } - return NS_OK; - } -}; - -GonkDiskSpaceWatcher::GonkDiskSpaceWatcher() : - mLastFreeSpace(UINT64_MAX), - mIsDiskFull(false), - mFreeSpace(UINT64_MAX), - mFd(-1) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(gHalDiskSpaceWatcher == nullptr); - - // Default values: 5MB for low threshold, 10MB for high threshold, and - // a timeout of 5 seconds. - mLowThreshold = Preferences::GetInt(WATCHER_PREF_LOW, 5) * 1024 * 1024; - mHighThreshold = Preferences::GetInt(WATCHER_PREF_HIGH, 10) * 1024 * 1024; - mTimeout = TimeDuration::FromSeconds(Preferences::GetInt(WATCHER_PREF_TIMEOUT, 5)); - mSizeDelta = Preferences::GetInt(WATCHER_PREF_SIZE_DELTA, 1) * 1024 * 1024; -} - -void -GonkDiskSpaceWatcher::DoStart() -{ - NS_ASSERTION(XRE_GetIOMessageLoop() == MessageLoopForIO::current(), - "Not on the correct message loop"); - - mFd = fanotify_init(FAN_CLASS_NOTIF, FAN_CLOEXEC | O_LARGEFILE); - if (mFd == -1) { - if (errno == ENOSYS) { - // Don't change these printf_stderr since we need these logs even - // in opt builds. - printf_stderr("Warning: No fanotify support in this device's kernel.\n"); -#if ANDROID_VERSION >= 19 - MOZ_CRASH("Fanotify support must be enabled in the kernel."); -#endif - } else { - printf_stderr("Error calling fanotify_init()"); - } - return; - } - - if (fanotify_mark(mFd, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_CLOSE, - 0, kWatchedPath) < 0) { - NS_WARNING("Error calling fanotify_mark"); - close(mFd); - mFd = -1; - return; - } - - if (!MessageLoopForIO::current()->WatchFileDescriptor( - mFd, /* persistent = */ true, - MessageLoopForIO::WATCH_READ, - &mReadWatcher, gHalDiskSpaceWatcher)) { - NS_WARNING("Unable to watch fanotify fd."); - close(mFd); - mFd = -1; - } -} - -void -GonkDiskSpaceWatcher::DoStop() -{ - NS_ASSERTION(XRE_GetIOMessageLoop() == MessageLoopForIO::current(), - "Not on the correct message loop"); - - if (mFd != -1) { - mReadWatcher.StopWatchingFileDescriptor(); - fanotify_mark(mFd, FAN_MARK_FLUSH, 0, 0, kWatchedPath); - close(mFd); - mFd = -1; - } - - // Dispatch the cleanup to the main thread. - nsCOMPtr<nsIRunnable> runnable = new DiskSpaceCleaner(); - NS_DispatchToMainThread(runnable); -} - -// We are called off the main thread, so we proxy first to the main thread -// before calling the xpcom object. -void -GonkDiskSpaceWatcher::NotifyUpdate() -{ - mLastTimestamp = TimeStamp::Now(); - mLastFreeSpace = mFreeSpace; - - nsCOMPtr<nsIRunnable> runnable = - new DiskSpaceNotifier(mIsDiskFull, mFreeSpace); - NS_DispatchToMainThread(runnable); -} - -void -GonkDiskSpaceWatcher::OnFileCanReadWithoutBlocking(int aFd) -{ - struct fanotify_event_metadata* fem = nullptr; - char buf[4096]; - struct statfs sfs; - int32_t len, rc; - - do { - len = read(aFd, buf, sizeof(buf)); - } while(len == -1 && errno == EINTR); - - // Bail out if the file is busy. - if (len < 0 && errno == ETXTBSY) { - return; - } - - // We should get an exact multiple of fanotify_event_metadata - if (len <= 0 || (len % FAN_EVENT_METADATA_LEN != 0)) { - MOZ_CRASH("About to crash: fanotify_event_metadata read error."); - } - - fem = reinterpret_cast<fanotify_event_metadata *>(buf); - - while (FAN_EVENT_OK(fem, len)) { - rc = fstatfs(fem->fd, &sfs); - if (rc < 0) { - NS_WARNING("Unable to stat fan_notify fd"); - } else { - bool firstRun = mFreeSpace == UINT64_MAX; - mFreeSpace = sfs.f_bavail * sfs.f_bsize; - // We change from full <-> free depending on the free space and the - // low and high thresholds. - // Once we are in 'full' mode we send updates for all size changes with - // a minimum of time between messages or when we cross a size change - // threshold. - if (firstRun) { - mIsDiskFull = mFreeSpace <= mLowThreshold; - // Always notify the current state at first run. - NotifyUpdate(); - } else if (!mIsDiskFull && (mFreeSpace <= mLowThreshold)) { - mIsDiskFull = true; - NotifyUpdate(); - } else if (mIsDiskFull && (mFreeSpace > mHighThreshold)) { - mIsDiskFull = false; - NotifyUpdate(); - } else if (mIsDiskFull) { - if (mTimeout < TimeStamp::Now() - mLastTimestamp || - mSizeDelta < llabs(mFreeSpace - mLastFreeSpace)) { - NotifyUpdate(); - } - } - } - close(fem->fd); - fem = FAN_EVENT_NEXT(fem, len); - } -} - -void -StartDiskSpaceWatcher() -{ - MOZ_ASSERT(NS_IsMainThread()); - - // Bail out if called several times. - if (gHalDiskSpaceWatcher != nullptr) { - return; - } - - gHalDiskSpaceWatcher = new GonkDiskSpaceWatcher(); - - XRE_GetIOMessageLoop()->PostTask( - NewNonOwningRunnableMethod(gHalDiskSpaceWatcher, &GonkDiskSpaceWatcher::DoStart)); -} - -void -StopDiskSpaceWatcher() -{ - MOZ_ASSERT(NS_IsMainThread()); - if (!gHalDiskSpaceWatcher) { - return; - } - - XRE_GetIOMessageLoop()->PostTask( - NewNonOwningRunnableMethod(gHalDiskSpaceWatcher, &GonkDiskSpaceWatcher::DoStop)); -} - -} // namespace hal_impl -} // namespace mozilla diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp deleted file mode 100644 index 05d9295a2..000000000 --- a/hal/gonk/GonkHal.cpp +++ /dev/null @@ -1,2045 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=8 et ft=cpp : */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <linux/android_alarm.h> -#include <math.h> -#include <regex.h> -#include <sched.h> -#include <stdio.h> -#include <sys/klog.h> -#include <sys/stat.h> -#include <sys/syscall.h> -#include <sys/resource.h> -#include <time.h> -#include <unistd.h> - -#include "mozilla/DebugOnly.h" - -#include "android/log.h" -#include "cutils/properties.h" -#include "hardware/hardware.h" -#include "hardware/lights.h" -#include "hardware_legacy/uevent.h" -#include "hardware_legacy/vibrator.h" -#include "hardware_legacy/power.h" -#include "libdisplay/GonkDisplay.h" -#include "utils/threads.h" - -#include "base/message_loop.h" -#include "base/task.h" - -#include "Hal.h" -#include "HalImpl.h" -#include "HalLog.h" -#include "mozilla/ArrayUtils.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/dom/battery/Constants.h" -#include "mozilla/DebugOnly.h" -#include "mozilla/FileUtils.h" -#include "mozilla/Monitor.h" -#include "mozilla/RefPtr.h" -#include "mozilla/Services.h" -#include "mozilla/StaticMutex.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/Preferences.h" -#include "mozilla/UniquePtrExtensions.h" -#include "nsAlgorithm.h" -#include "nsPrintfCString.h" -#include "nsIObserver.h" -#include "nsIObserverService.h" -#include "nsIRecoveryService.h" -#include "nsIRunnable.h" -#include "nsScreenManagerGonk.h" -#include "nsThreadUtils.h" -#include "nsThreadUtils.h" -#include "nsIThread.h" -#include "nsXULAppAPI.h" -#include "OrientationObserver.h" -#include "UeventPoller.h" -#include "nsIWritablePropertyBag2.h" -#include <algorithm> - -#define NsecPerMsec 1000000LL -#define NsecPerSec 1000000000 - -// The header linux/oom.h is not available in bionic libc. We -// redefine some of its constants here. - -#ifndef OOM_DISABLE -#define OOM_DISABLE (-17) -#endif - -#ifndef OOM_ADJUST_MIN -#define OOM_ADJUST_MIN (-16) -#endif - -#ifndef OOM_ADJUST_MAX -#define OOM_ADJUST_MAX 15 -#endif - -#ifndef OOM_SCORE_ADJ_MIN -#define OOM_SCORE_ADJ_MIN (-1000) -#endif - -#ifndef OOM_SCORE_ADJ_MAX -#define OOM_SCORE_ADJ_MAX 1000 -#endif - -#ifndef BATTERY_CHARGING_ARGB -#define BATTERY_CHARGING_ARGB 0x00FF0000 -#endif -#ifndef BATTERY_FULL_ARGB -#define BATTERY_FULL_ARGB 0x0000FF00 -#endif - -using namespace mozilla; -using namespace mozilla::hal; -using namespace mozilla::dom; - -namespace mozilla { -namespace hal_impl { - -/** - * These are defined by libhardware, specifically, hardware/libhardware/include/hardware/lights.h - * in the gonk subsystem. - * If these change and are exposed to JS, make sure nsIHal.idl is updated as well. - */ -enum LightType { - eHalLightID_Backlight = 0, - eHalLightID_Keyboard = 1, - eHalLightID_Buttons = 2, - eHalLightID_Battery = 3, - eHalLightID_Notifications = 4, - eHalLightID_Attention = 5, - eHalLightID_Bluetooth = 6, - eHalLightID_Wifi = 7, - eHalLightID_Count // This should stay at the end -}; -enum LightMode { - eHalLightMode_User = 0, // brightness is managed by user setting - eHalLightMode_Sensor = 1, // brightness is managed by a light sensor - eHalLightMode_Count -}; -enum FlashMode { - eHalLightFlash_None = 0, - eHalLightFlash_Timed = 1, // timed flashing. Use flashOnMS and flashOffMS for timing - eHalLightFlash_Hardware = 2, // hardware assisted flashing - eHalLightFlash_Count -}; - -struct LightConfiguration { - LightType light; - LightMode mode; - FlashMode flash; - uint32_t flashOnMS; - uint32_t flashOffMS; - uint32_t color; -}; - -static light_device_t* sLights[eHalLightID_Count]; // will be initialized to nullptr - -static light_device_t* -GetDevice(hw_module_t* module, char const* name) -{ - int err; - hw_device_t* device; - err = module->methods->open(module, name, &device); - if (err == 0) { - return (light_device_t*)device; - } else { - return nullptr; - } -} - -static void -InitLights() -{ - // assume that if backlight is nullptr, nothing has been set yet - // if this is not true, the initialization will occur everytime a light is read or set! - if (!sLights[eHalLightID_Backlight]) { - int err; - hw_module_t* module; - - err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); - if (err == 0) { - sLights[eHalLightID_Backlight] - = GetDevice(module, LIGHT_ID_BACKLIGHT); - sLights[eHalLightID_Keyboard] - = GetDevice(module, LIGHT_ID_KEYBOARD); - sLights[eHalLightID_Buttons] - = GetDevice(module, LIGHT_ID_BUTTONS); - sLights[eHalLightID_Battery] - = GetDevice(module, LIGHT_ID_BATTERY); - sLights[eHalLightID_Notifications] - = GetDevice(module, LIGHT_ID_NOTIFICATIONS); - sLights[eHalLightID_Attention] - = GetDevice(module, LIGHT_ID_ATTENTION); - sLights[eHalLightID_Bluetooth] - = GetDevice(module, LIGHT_ID_BLUETOOTH); - sLights[eHalLightID_Wifi] - = GetDevice(module, LIGHT_ID_WIFI); - } - } -} - -/** - * The state last set for the lights until liblights supports - * getting the light state. - */ -static light_state_t sStoredLightState[eHalLightID_Count]; - -/** -* Set the value of a light to a particular color, with a specific flash pattern. -* light specifices which light. See Hal.idl for the list of constants -* mode specifies user set or based on ambient light sensor -* flash specifies whether or how to flash the light -* flashOnMS and flashOffMS specify the pattern for XXX flash mode -* color specifies the color. If the light doesn't support color, the given color is -* transformed into a brightness, or just an on/off if that is all the light is capable of. -* returns true if successful and false if failed. -*/ -static bool -SetLight(LightType light, const LightConfiguration& aConfig) -{ - light_state_t state; - - InitLights(); - - if (light < 0 || light >= eHalLightID_Count || - sLights[light] == nullptr) { - return false; - } - - memset(&state, 0, sizeof(light_state_t)); - state.color = aConfig.color; - state.flashMode = aConfig.flash; - state.flashOnMS = aConfig.flashOnMS; - state.flashOffMS = aConfig.flashOffMS; - state.brightnessMode = aConfig.mode; - - sLights[light]->set_light(sLights[light], &state); - sStoredLightState[light] = state; - return true; -} - -/** -* GET the value of a light returning a particular color, with a specific flash pattern. -* returns true if successful and false if failed. -*/ -static bool -GetLight(LightType light, LightConfiguration* aConfig) -{ - light_state_t state; - - if (light < 0 || light >= eHalLightID_Count || - sLights[light] == nullptr) { - return false; - } - - memset(&state, 0, sizeof(light_state_t)); - state = sStoredLightState[light]; - - aConfig->light = light; - aConfig->color = state.color; - aConfig->flash = FlashMode(state.flashMode); - aConfig->flashOnMS = state.flashOnMS; - aConfig->flashOffMS = state.flashOffMS; - aConfig->mode = LightMode(state.brightnessMode); - - return true; -} - -namespace { - -/** - * This runnable runs for the lifetime of the program, once started. It's - * responsible for "playing" vibration patterns. - */ -class VibratorRunnable final - : public nsIRunnable - , public nsIObserver -{ -public: - VibratorRunnable() - : mMonitor("VibratorRunnable") - , mIndex(0) - { - nsCOMPtr<nsIObserverService> os = services::GetObserverService(); - if (!os) { - NS_WARNING("Could not get observer service!"); - return; - } - - os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); - } - - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIRUNNABLE - NS_DECL_NSIOBSERVER - - // Run on the main thread, not the vibrator thread. - void Vibrate(const nsTArray<uint32_t> &pattern); - void CancelVibrate(); - - static bool ShuttingDown() { return sShuttingDown; } - -protected: - ~VibratorRunnable() {} - -private: - Monitor mMonitor; - - // The currently-playing pattern. - nsTArray<uint32_t> mPattern; - - // The index we're at in the currently-playing pattern. If mIndex >= - // mPattern.Length(), then we're not currently playing anything. - uint32_t mIndex; - - // Set to true in our shutdown observer. When this is true, we kill the - // vibrator thread. - static bool sShuttingDown; -}; - -NS_IMPL_ISUPPORTS(VibratorRunnable, nsIRunnable, nsIObserver); - -bool VibratorRunnable::sShuttingDown = false; - -static StaticRefPtr<VibratorRunnable> sVibratorRunnable; - -NS_IMETHODIMP -VibratorRunnable::Run() -{ - MonitorAutoLock lock(mMonitor); - - // We currently assume that mMonitor.Wait(X) waits for X milliseconds. But in - // reality, the kernel might not switch to this thread for some time after the - // wait expires. So there's potential for some inaccuracy here. - // - // This doesn't worry me too much. Note that we don't even start vibrating - // immediately when VibratorRunnable::Vibrate is called -- we go through a - // condvar onto another thread. Better just to be chill about small errors in - // the timing here. - - while (!sShuttingDown) { - if (mIndex < mPattern.Length()) { - uint32_t duration = mPattern[mIndex]; - if (mIndex % 2 == 0) { - vibrator_on(duration); - } - mIndex++; - mMonitor.Wait(PR_MillisecondsToInterval(duration)); - } - else { - mMonitor.Wait(); - } - } - sVibratorRunnable = nullptr; - return NS_OK; -} - -NS_IMETHODIMP -VibratorRunnable::Observe(nsISupports *subject, const char *topic, - const char16_t *data) -{ - MOZ_ASSERT(strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0); - MonitorAutoLock lock(mMonitor); - sShuttingDown = true; - mMonitor.Notify(); - - return NS_OK; -} - -void -VibratorRunnable::Vibrate(const nsTArray<uint32_t> &pattern) -{ - MonitorAutoLock lock(mMonitor); - mPattern = pattern; - mIndex = 0; - mMonitor.Notify(); -} - -void -VibratorRunnable::CancelVibrate() -{ - MonitorAutoLock lock(mMonitor); - mPattern.Clear(); - mPattern.AppendElement(0); - mIndex = 0; - mMonitor.Notify(); -} - -void -EnsureVibratorThreadInitialized() -{ - if (sVibratorRunnable) { - return; - } - - sVibratorRunnable = new VibratorRunnable(); - nsCOMPtr<nsIThread> thread; - NS_NewThread(getter_AddRefs(thread), sVibratorRunnable); -} - -} // namespace - -void -Vibrate(const nsTArray<uint32_t> &pattern, const hal::WindowIdentifier &) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (VibratorRunnable::ShuttingDown()) { - return; - } - EnsureVibratorThreadInitialized(); - sVibratorRunnable->Vibrate(pattern); -} - -void -CancelVibrate(const hal::WindowIdentifier &) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (VibratorRunnable::ShuttingDown()) { - return; - } - EnsureVibratorThreadInitialized(); - sVibratorRunnable->CancelVibrate(); -} - -namespace { - -class BatteryUpdater : public Runnable { -public: - NS_IMETHOD Run() override - { - hal::BatteryInformation info; - hal_impl::GetCurrentBatteryInformation(&info); - - // Control the battery indicator (led light) here using BatteryInformation - // we just retrieved. - uint32_t color = 0; // Format: 0x00rrggbb. - if (info.charging() && (info.level() == 1)) { - // Charging and battery full. - color = BATTERY_FULL_ARGB; - } else if (info.charging() && (info.level() < 1)) { - // Charging but not full. - color = BATTERY_CHARGING_ARGB; - } // else turn off battery indicator. - - LightConfiguration aConfig; - aConfig.light = eHalLightID_Battery; - aConfig.mode = eHalLightMode_User; - aConfig.flash = eHalLightFlash_None; - aConfig.flashOnMS = aConfig.flashOffMS = 0; - aConfig.color = color; - - SetLight(eHalLightID_Battery, aConfig); - - hal::NotifyBatteryChange(info); - - { - // bug 975667 - // Gecko gonk hal is required to emit battery charging/level notification via nsIObserverService. - // This is useful for XPCOM components that are not statically linked to Gecko and cannot call - // hal::EnableBatteryNotifications - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - nsCOMPtr<nsIWritablePropertyBag2> propbag = - do_CreateInstance("@mozilla.org/hash-property-bag;1"); - if (obsService && propbag) { - propbag->SetPropertyAsBool(NS_LITERAL_STRING("charging"), - info.charging()); - propbag->SetPropertyAsDouble(NS_LITERAL_STRING("level"), - info.level()); - - obsService->NotifyObservers(propbag, "gonkhal-battery-notifier", nullptr); - } - } - - return NS_OK; - } -}; - -} // namespace - -class BatteryObserver final : public IUeventObserver -{ -public: - NS_INLINE_DECL_REFCOUNTING(BatteryObserver) - - BatteryObserver() - :mUpdater(new BatteryUpdater()) - { - } - - virtual void Notify(const NetlinkEvent &aEvent) - { - // 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); - } - } - -protected: - ~BatteryObserver() {} - -private: - RefPtr<BatteryUpdater> mUpdater; -}; - -// sBatteryObserver is owned by the IO thread. Only the IO thread may -// create or destroy it. -static StaticRefPtr<BatteryObserver> sBatteryObserver; - -static void -RegisterBatteryObserverIOThread() -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - MOZ_ASSERT(!sBatteryObserver); - - sBatteryObserver = new BatteryObserver(); - RegisterUeventListener(sBatteryObserver); -} - -void -EnableBatteryNotifications() -{ - XRE_GetIOMessageLoop()->PostTask( - NewRunnableFunction(RegisterBatteryObserverIOThread)); -} - -static void -UnregisterBatteryObserverIOThread() -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - MOZ_ASSERT(sBatteryObserver); - - UnregisterUeventListener(sBatteryObserver); - sBatteryObserver = nullptr; -} - -void -DisableBatteryNotifications() -{ - XRE_GetIOMessageLoop()->PostTask( - NewRunnableFunction(UnregisterBatteryObserverIOThread)); -} - -static bool -GetCurrentBatteryCharge(int* aCharge) -{ - bool success = ReadSysFile("/sys/class/power_supply/battery/capacity", - aCharge); - if (!success) { - return false; - } - - #ifdef DEBUG - if ((*aCharge < 0) || (*aCharge > 100)) { - HAL_LOG("charge level contains unknown value: %d", *aCharge); - } - #endif - - return (*aCharge >= 0) && (*aCharge <= 100); -} - -static bool -GetCurrentBatteryCharging(int* aCharging) -{ - static const DebugOnly<int> BATTERY_NOT_CHARGING = 0; - static const int BATTERY_CHARGING_USB = 1; - static const int BATTERY_CHARGING_AC = 2; - - // Generic device support - - int chargingSrc; - bool success = - ReadSysFile("/sys/class/power_supply/battery/charging_source", &chargingSrc); - - if (success) { - #ifdef DEBUG - if (chargingSrc != BATTERY_NOT_CHARGING && - chargingSrc != BATTERY_CHARGING_USB && - chargingSrc != BATTERY_CHARGING_AC) { - HAL_LOG("charging_source contained unknown value: %d", chargingSrc); - } - #endif - - *aCharging = (chargingSrc == BATTERY_CHARGING_USB || - chargingSrc == BATTERY_CHARGING_AC); - return true; - } - - // Otoro device support - - char chargingSrcString[16]; - - success = ReadSysFile("/sys/class/power_supply/battery/status", - chargingSrcString, sizeof(chargingSrcString)); - if (success) { - *aCharging = strcmp(chargingSrcString, "Charging") == 0 || - strcmp(chargingSrcString, "Full") == 0; - return true; - } - - return false; -} - -void -GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo) -{ - int charge; - static bool previousCharging = false; - static double previousLevel = 0.0, remainingTime = 0.0; - static struct timespec lastLevelChange; - struct timespec now; - double dtime, dlevel; - - if (GetCurrentBatteryCharge(&charge)) { - aBatteryInfo->level() = (double)charge / 100.0; - } else { - aBatteryInfo->level() = dom::battery::kDefaultLevel; - } - - int charging; - - if (GetCurrentBatteryCharging(&charging)) { - aBatteryInfo->charging() = charging; - } else { - aBatteryInfo->charging() = true; - } - - if (aBatteryInfo->charging() != previousCharging){ - aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime; - memset(&lastLevelChange, 0, sizeof(struct timespec)); - remainingTime = 0.0; - } - - if (aBatteryInfo->charging()) { - if (aBatteryInfo->level() == 1.0) { - aBatteryInfo->remainingTime() = dom::battery::kDefaultRemainingTime; - } else if (aBatteryInfo->level() != previousLevel){ - if (lastLevelChange.tv_sec != 0) { - clock_gettime(CLOCK_MONOTONIC, &now); - dtime = now.tv_sec - lastLevelChange.tv_sec; - dlevel = aBatteryInfo->level() - previousLevel; - - if (dlevel <= 0.0) { - aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime; - } else { - remainingTime = (double) round(dtime / dlevel * (1.0 - aBatteryInfo->level())); - aBatteryInfo->remainingTime() = remainingTime; - } - - lastLevelChange = now; - } else { // lastLevelChange.tv_sec == 0 - clock_gettime(CLOCK_MONOTONIC, &lastLevelChange); - aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime; - } - - } else { - clock_gettime(CLOCK_MONOTONIC, &now); - dtime = now.tv_sec - lastLevelChange.tv_sec; - if (dtime < remainingTime) { - aBatteryInfo->remainingTime() = round(remainingTime - dtime); - } else { - aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime; - } - - } - - } else { - if (aBatteryInfo->level() == 0.0) { - aBatteryInfo->remainingTime() = dom::battery::kDefaultRemainingTime; - } else if (aBatteryInfo->level() != previousLevel){ - if (lastLevelChange.tv_sec != 0) { - clock_gettime(CLOCK_MONOTONIC, &now); - dtime = now.tv_sec - lastLevelChange.tv_sec; - dlevel = previousLevel - aBatteryInfo->level(); - - if (dlevel <= 0.0) { - aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime; - } else { - remainingTime = (double) round(dtime / dlevel * aBatteryInfo->level()); - aBatteryInfo->remainingTime() = remainingTime; - } - - lastLevelChange = now; - } else { // lastLevelChange.tv_sec == 0 - clock_gettime(CLOCK_MONOTONIC, &lastLevelChange); - aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime; - } - - } else { - clock_gettime(CLOCK_MONOTONIC, &now); - dtime = now.tv_sec - lastLevelChange.tv_sec; - if (dtime < remainingTime) { - aBatteryInfo->remainingTime() = round(remainingTime - dtime); - } else { - aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime; - } - - } - } - - previousCharging = aBatteryInfo->charging(); - previousLevel = aBatteryInfo->level(); -} - -namespace { - -// We can write to screenEnabledFilename to enable/disable the screen, but when -// we read, we always get "mem"! So we have to keep track ourselves whether -// the screen is on or not. -bool sScreenEnabled = true; - -// We can read wakeLockFilename to find out whether the cpu wake lock -// is already acquired, but reading and parsing it is a lot more work -// than tracking it ourselves, and it won't be accurate anyway (kernel -// internal wake locks aren't counted here.) -bool sCpuSleepAllowed = true; - -// Some CPU wake locks may be acquired internally in HAL. We use a counter to -// keep track of these needs. Note we have to hold |sInternalLockCpuMutex| -// when reading or writing this variable to ensure thread-safe. -int32_t sInternalLockCpuCount = 0; - -} // namespace - -bool -GetScreenEnabled() -{ - return sScreenEnabled; -} - -void -SetScreenEnabled(bool aEnabled) -{ - GetGonkDisplay()->SetEnabled(aEnabled); - sScreenEnabled = aEnabled; -} - -bool -GetKeyLightEnabled() -{ - LightConfiguration config; - bool ok = GetLight(eHalLightID_Buttons, &config); - if (ok) { - return (config.color != 0x00000000); - } - return false; -} - -void -SetKeyLightEnabled(bool aEnabled) -{ - LightConfiguration config; - config.mode = eHalLightMode_User; - config.flash = eHalLightFlash_None; - config.flashOnMS = config.flashOffMS = 0; - config.color = 0x00000000; - - if (aEnabled) { - // Convert the value in [0, 1] to an int between 0 and 255 and then convert - // it to a color. Note that the high byte is FF, corresponding to the alpha - // channel. - double brightness = GetScreenBrightness(); - uint32_t val = static_cast<int>(round(brightness * 255.0)); - uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val; - - config.color = color; - } - - SetLight(eHalLightID_Buttons, config); - SetLight(eHalLightID_Keyboard, config); -} - -double -GetScreenBrightness() -{ - LightConfiguration config; - LightType light = eHalLightID_Backlight; - - bool ok = GetLight(light, &config); - if (ok) { - // backlight is brightness only, so using one of the RGB elements as value. - int brightness = config.color & 0xFF; - return brightness / 255.0; - } - // If GetLight fails, it's because the light doesn't exist. So return - // a value corresponding to "off". - return 0; -} - -void -SetScreenBrightness(double brightness) -{ - // Don't use De Morgan's law to push the ! into this expression; we want to - // catch NaN too. - if (!(0 <= brightness && brightness <= 1)) { - HAL_LOG("SetScreenBrightness: Dropping illegal brightness %f.", brightness); - return; - } - - // Convert the value in [0, 1] to an int between 0 and 255 and convert to a color - // note that the high byte is FF, corresponding to the alpha channel. - uint32_t val = static_cast<int>(round(brightness * 255.0)); - uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val; - - LightConfiguration config; - config.mode = eHalLightMode_User; - config.flash = eHalLightFlash_None; - config.flashOnMS = config.flashOffMS = 0; - config.color = color; - SetLight(eHalLightID_Backlight, config); - if (GetKeyLightEnabled()) { - SetLight(eHalLightID_Buttons, config); - SetLight(eHalLightID_Keyboard, config); - } -} - -static StaticMutex sInternalLockCpuMutex; - -static void -UpdateCpuSleepState() -{ - const char *wakeLockFilename = "/sys/power/wake_lock"; - const char *wakeUnlockFilename = "/sys/power/wake_unlock"; - - sInternalLockCpuMutex.AssertCurrentThreadOwns(); - bool allowed = sCpuSleepAllowed && !sInternalLockCpuCount; - WriteSysFile(allowed ? wakeUnlockFilename : wakeLockFilename, "gecko"); -} - -static void -InternalLockCpu() { - StaticMutexAutoLock lock(sInternalLockCpuMutex); - ++sInternalLockCpuCount; - UpdateCpuSleepState(); -} - -static void -InternalUnlockCpu() { - StaticMutexAutoLock lock(sInternalLockCpuMutex); - --sInternalLockCpuCount; - UpdateCpuSleepState(); -} - -bool -GetCpuSleepAllowed() -{ - return sCpuSleepAllowed; -} - -void -SetCpuSleepAllowed(bool aAllowed) -{ - StaticMutexAutoLock lock(sInternalLockCpuMutex); - sCpuSleepAllowed = aAllowed; - UpdateCpuSleepState(); -} - -void -AdjustSystemClock(int64_t aDeltaMilliseconds) -{ - int fd; - struct timespec now; - - if (aDeltaMilliseconds == 0) { - return; - } - - // Preventing context switch before setting system clock - sched_yield(); - clock_gettime(CLOCK_REALTIME, &now); - now.tv_sec += (time_t)(aDeltaMilliseconds / 1000LL); - now.tv_nsec += (long)((aDeltaMilliseconds % 1000LL) * NsecPerMsec); - if (now.tv_nsec >= NsecPerSec) { - now.tv_sec += 1; - now.tv_nsec -= NsecPerSec; - } - - if (now.tv_nsec < 0) { - now.tv_nsec += NsecPerSec; - now.tv_sec -= 1; - } - - do { - fd = open("/dev/alarm", O_RDWR); - } while (fd == -1 && errno == EINTR); - ScopedClose autoClose(fd); - if (fd < 0) { - HAL_LOG("Failed to open /dev/alarm: %s", strerror(errno)); - return; - } - - if (ioctl(fd, ANDROID_ALARM_SET_RTC, &now) < 0) { - HAL_LOG("ANDROID_ALARM_SET_RTC failed: %s", strerror(errno)); - } - - hal::NotifySystemClockChange(aDeltaMilliseconds); -} - -int32_t -GetTimezoneOffset() -{ - PRExplodedTime prTime; - PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prTime); - - // Daylight saving time (DST) will be taken into account. - int32_t offset = prTime.tm_params.tp_gmt_offset; - offset += prTime.tm_params.tp_dst_offset; - - // Returns the timezone offset relative to UTC in minutes. - return -(offset / 60); -} - -static int32_t sKernelTimezoneOffset = 0; - -static void -UpdateKernelTimezone(int32_t timezoneOffset) -{ - if (sKernelTimezoneOffset == timezoneOffset) { - return; - } - - // Tell the kernel about the new time zone as well, so that FAT filesystems - // will get local timestamps rather than UTC timestamps. - // - // We assume that /init.rc has a sysclktz entry so that settimeofday has - // already been called once before we call it (there is a side-effect in - // the kernel the very first time settimeofday is called where it does some - // special processing if you only set the timezone). - struct timezone tz; - memset(&tz, 0, sizeof(tz)); - tz.tz_minuteswest = timezoneOffset; - settimeofday(nullptr, &tz); - sKernelTimezoneOffset = timezoneOffset; -} - -void -SetTimezone(const nsCString& aTimezoneSpec) -{ - if (aTimezoneSpec.Equals(GetTimezone())) { - // Even though the timezone hasn't changed, we still need to tell the - // kernel what the current timezone is. The timezone is persisted in - // a property and doesn't change across reboots, but the kernel still - // needs to be updated on every boot. - UpdateKernelTimezone(GetTimezoneOffset()); - return; - } - - int32_t oldTimezoneOffsetMinutes = GetTimezoneOffset(); - property_set("persist.sys.timezone", aTimezoneSpec.get()); - // This function is automatically called by the other time conversion - // functions that depend on the timezone. To be safe, we call it manually. - tzset(); - int32_t newTimezoneOffsetMinutes = GetTimezoneOffset(); - UpdateKernelTimezone(newTimezoneOffsetMinutes); - hal::NotifySystemTimezoneChange( - hal::SystemTimezoneChangeInformation( - oldTimezoneOffsetMinutes, newTimezoneOffsetMinutes)); -} - -nsCString -GetTimezone() -{ - char timezone[32]; - property_get("persist.sys.timezone", timezone, ""); - return nsCString(timezone); -} - -void -EnableSystemClockChangeNotifications() -{ -} - -void -DisableSystemClockChangeNotifications() -{ -} - -void -EnableSystemTimezoneChangeNotifications() -{ -} - -void -DisableSystemTimezoneChangeNotifications() -{ -} - -// Nothing to do here. Gonk widgetry always listens for screen -// orientation changes. -void -EnableScreenConfigurationNotifications() -{ -} - -void -DisableScreenConfigurationNotifications() -{ -} - -void -GetCurrentScreenConfiguration(hal::ScreenConfiguration* aScreenConfiguration) -{ - RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen(); - *aScreenConfiguration = screen->GetConfiguration(); -} - -bool -LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation) -{ - return OrientationObserver::GetInstance()->LockScreenOrientation(aOrientation); -} - -void -UnlockScreenOrientation() -{ - OrientationObserver::GetInstance()->UnlockScreenOrientation(); -} - -// This thread will wait for the alarm firing by a blocking IO. -static pthread_t sAlarmFireWatcherThread; - -// If |sAlarmData| is non-null, it's owned by the alarm-watcher thread. -struct AlarmData { -public: - AlarmData(int aFd) : mFd(aFd), - mGeneration(sNextGeneration++), - mShuttingDown(false) {} - ScopedClose mFd; - int mGeneration; - bool mShuttingDown; - - static int sNextGeneration; - -}; - -int AlarmData::sNextGeneration = 0; - -AlarmData* sAlarmData = nullptr; - -class AlarmFiredEvent : public Runnable { -public: - AlarmFiredEvent(int aGeneration) : mGeneration(aGeneration) {} - - NS_IMETHOD Run() override { - // Guard against spurious notifications caused by an alarm firing - // concurrently with it being disabled. - if (sAlarmData && !sAlarmData->mShuttingDown && - mGeneration == sAlarmData->mGeneration) { - hal::NotifyAlarmFired(); - } - // The fired alarm event has been delivered to the observer (if needed); - // we can now release a CPU wake lock. - InternalUnlockCpu(); - return NS_OK; - } - -private: - int mGeneration; -}; - -// Runs on alarm-watcher thread. -static void -DestroyAlarmData(void* aData) -{ - AlarmData* alarmData = static_cast<AlarmData*>(aData); - delete alarmData; -} - -// Runs on alarm-watcher thread. -void ShutDownAlarm(int aSigno) -{ - if (aSigno == SIGUSR1 && sAlarmData) { - sAlarmData->mShuttingDown = true; - } - return; -} - -static void* -WaitForAlarm(void* aData) -{ - pthread_cleanup_push(DestroyAlarmData, aData); - - AlarmData* alarmData = static_cast<AlarmData*>(aData); - - while (!alarmData->mShuttingDown) { - int alarmTypeFlags = 0; - - // ALARM_WAIT apparently will block even if an alarm hasn't been - // programmed, although this behavior doesn't seem to be - // documented. We rely on that here to avoid spinning the CPU - // while awaiting an alarm to be programmed. - do { - alarmTypeFlags = ioctl(alarmData->mFd, ANDROID_ALARM_WAIT); - } while (alarmTypeFlags < 0 && errno == EINTR && - !alarmData->mShuttingDown); - - if (!alarmData->mShuttingDown && alarmTypeFlags >= 0 && - (alarmTypeFlags & ANDROID_ALARM_RTC_WAKEUP_MASK)) { - // To make sure the observer can get the alarm firing notification - // *on time* (the system won't sleep during the process in any way), - // we need to acquire a CPU wake lock before firing the alarm event. - InternalLockCpu(); - RefPtr<AlarmFiredEvent> event = - new AlarmFiredEvent(alarmData->mGeneration); - NS_DispatchToMainThread(event); - } - } - - pthread_cleanup_pop(1); - return nullptr; -} - -bool -EnableAlarm() -{ - MOZ_ASSERT(!sAlarmData); - - int alarmFd = open("/dev/alarm", O_RDWR); - if (alarmFd < 0) { - HAL_LOG("Failed to open alarm device: %s.", strerror(errno)); - return false; - } - - UniquePtr<AlarmData> alarmData = MakeUnique<AlarmData>(alarmFd); - - struct sigaction actions; - memset(&actions, 0, sizeof(actions)); - sigemptyset(&actions.sa_mask); - actions.sa_flags = 0; - actions.sa_handler = ShutDownAlarm; - if (sigaction(SIGUSR1, &actions, nullptr)) { - HAL_LOG("Failed to set SIGUSR1 signal for alarm-watcher thread."); - return false; - } - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - int status = pthread_create(&sAlarmFireWatcherThread, &attr, WaitForAlarm, - alarmData.get()); - if (status) { - alarmData.reset(); - HAL_LOG("Failed to create alarm-watcher thread. Status: %d.", status); - return false; - } - - pthread_attr_destroy(&attr); - - // The thread owns this now. We only hold a pointer. - sAlarmData = alarmData.release(); - return true; -} - -void -DisableAlarm() -{ - MOZ_ASSERT(sAlarmData); - - // NB: this must happen-before the thread cancellation. - sAlarmData = nullptr; - - // The cancel will interrupt the thread and destroy it, freeing the - // data pointed at by sAlarmData. - DebugOnly<int> err = pthread_kill(sAlarmFireWatcherThread, SIGUSR1); - MOZ_ASSERT(!err); -} - -bool -SetAlarm(int32_t aSeconds, int32_t aNanoseconds) -{ - if (!sAlarmData) { - HAL_LOG("We should have enabled the alarm."); - return false; - } - - struct timespec ts; - ts.tv_sec = aSeconds; - ts.tv_nsec = aNanoseconds; - - // Currently we only support RTC wakeup alarm type. - const int result = ioctl(sAlarmData->mFd, - ANDROID_ALARM_SET(ANDROID_ALARM_RTC_WAKEUP), &ts); - - if (result < 0) { - HAL_LOG("Unable to set alarm: %s.", strerror(errno)); - return false; - } - - return true; -} - -static int -OomAdjOfOomScoreAdj(int aOomScoreAdj) -{ - // Convert OOM adjustment from the domain of /proc/<pid>/oom_score_adj - // to the domain of /proc/<pid>/oom_adj. - - int adj; - - if (aOomScoreAdj < 0) { - adj = (OOM_DISABLE * aOomScoreAdj) / OOM_SCORE_ADJ_MIN; - } else { - adj = (OOM_ADJUST_MAX * aOomScoreAdj) / OOM_SCORE_ADJ_MAX; - } - - return adj; -} - -static void -RoundOomScoreAdjUpWithLRU(int& aOomScoreAdj, uint32_t aLRU) -{ - // We want to add minimum value to round OomScoreAdj up according to - // the steps by aLRU. - aOomScoreAdj += - ceil(((float)OOM_SCORE_ADJ_MAX / OOM_ADJUST_MAX) * aLRU); -} - -#define OOM_LOG(level, args...) __android_log_print(level, "OomLogger", ##args) -class OomVictimLogger final - : public nsIObserver -{ -public: - OomVictimLogger() - : mLastLineChecked(-1.0), - mRegexes(nullptr) - { - // Enable timestamps in kernel's printk - WriteSysFile("/sys/module/printk/parameters/time", "Y"); - } - - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - -protected: - ~OomVictimLogger() {} - -private: - double mLastLineChecked; - UniqueFreePtr<regex_t> mRegexes; -}; -NS_IMPL_ISUPPORTS(OomVictimLogger, nsIObserver); - -NS_IMETHODIMP -OomVictimLogger::Observe( - nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - nsDependentCString event_type(aTopic); - if (!event_type.EqualsLiteral("ipc:content-shutdown")) { - return NS_OK; - } - - // OOM message finding regexes - const char* const regexes_raw[] = { - ".*select.*to kill.*", - ".*send sigkill to.*", - ".*lowmem_shrink.*", - ".*[Oo]ut of [Mm]emory.*", - ".*[Kk]ill [Pp]rocess.*", - ".*[Kk]illed [Pp]rocess.*", - ".*oom-killer.*", - // The regexes below are for the output of dump_task from oom_kill.c - // 1st - title 2nd - body lines (8 ints and a string) - // oom_adj and oom_score_adj can be negative - "\\[ pid \\] uid tgid total_vm rss cpu oom_adj oom_score_adj name", - "\\[.*[0-9][0-9]*\\][ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*[0-9][0-9]*[ ]*.[0-9][0-9]*[ ]*.[0-9][0-9]*.*" - }; - const size_t regex_count = ArrayLength(regexes_raw); - - // Compile our regex just in time - if (!mRegexes) { - UniqueFreePtr<regex_t> regexes( - static_cast<regex_t*>(malloc(sizeof(regex_t) * regex_count)) - ); - mRegexes.swap(regexes); - for (size_t i = 0; i < regex_count; i++) { - int compilation_err = - regcomp(&(mRegexes.get()[i]), regexes_raw[i], REG_NOSUB); - if (compilation_err) { - OOM_LOG(ANDROID_LOG_ERROR, "Cannot compile regex \"%s\"\n", regexes_raw[i]); - return NS_OK; - } - } - } - -#ifndef KLOG_SIZE_BUFFER - // Upstream bionic in commit - // e249b059637b49a285ed9f58a2a18bfd054e5d95 - // deprecated the old klog defs. - // Our current bionic does not hit this - // change yet so handle the future change. - // (ICS doesn't have KLOG_SIZE_BUFFER but - // JB and onwards does.) - #define KLOG_SIZE_BUFFER KLOG_WRITE -#endif - // Retreive kernel log - int msg_buf_size = klogctl(KLOG_SIZE_BUFFER, NULL, 0); - UniqueFreePtr<char> msg_buf(static_cast<char *>(malloc(msg_buf_size + 1))); - int read_size = klogctl(KLOG_READ_ALL, msg_buf.get(), msg_buf_size); - - // Turn buffer into cstring - read_size = read_size > msg_buf_size ? msg_buf_size : read_size; - msg_buf.get()[read_size] = '\0'; - - // Foreach line - char* line_end; - char* line_begin = msg_buf.get(); - for (; (line_end = strchr(line_begin, '\n')); line_begin = line_end + 1) { - // make line into cstring - *line_end = '\0'; - - // Note: Kernel messages look like: - // <5>[63648.286409] sd 35:0:0:0: Attached scsi generic sg1 type 0 - // 5 is the loging level - // [*] is the time timestamp, seconds since boot - // last comes the logged message - - // Since the logging level can be a string we must - // skip it since scanf lacks wildcard matching - char* timestamp_begin = strchr(line_begin, '['); - char after_float; - double lineTimestamp = -1; - bool lineTimestampFound = false; - if (timestamp_begin && - // Note: scanf treats a ' ' as [ ]* - // Note: scanf treats [ %lf] as [ %lf thus we must check - // for the closing bracket outselves. - 2 == sscanf(timestamp_begin, "[ %lf%c", &lineTimestamp, &after_float) && - after_float == ']') { - if (lineTimestamp <= mLastLineChecked) { - continue; - } - - lineTimestampFound = true; - mLastLineChecked = lineTimestamp; - } - - // Log interesting lines - for (size_t i = 0; i < regex_count; i++) { - int matching = !regexec(&(mRegexes.get()[i]), line_begin, 0, NULL, 0); - if (matching) { - // Log content of kernel message. We try to skip the ], but if for - // some reason (most likely due to buffer overflow/wraparound), we - // can't find the ] then we just log the entire line. - char* endOfTimestamp = strchr(line_begin, ']'); - if (endOfTimestamp && endOfTimestamp[1] == ' ') { - // skip the ] and the space that follows it - line_begin = endOfTimestamp + 2; - } - if (!lineTimestampFound) { - OOM_LOG(ANDROID_LOG_WARN, "following kill message may be a duplicate"); - } - OOM_LOG(ANDROID_LOG_ERROR, "[Kill]: %s\n", line_begin); - break; - } - } - } - - return NS_OK; -} - -/** - * Wraps a particular ProcessPriority, giving us easy access to the prefs that - * are relevant to it. - * - * Creating a PriorityClass also ensures that the control group is created. - */ -class PriorityClass -{ -public: - /** - * Create a PriorityClass for the given ProcessPriority. This implicitly - * reads the relevant prefs and opens the cgroup.procs file of the relevant - * control group caching its file descriptor for later use. - */ - PriorityClass(ProcessPriority aPriority); - - /** - * Closes the file descriptor for the cgroup.procs file of the associated - * control group. - */ - ~PriorityClass(); - - PriorityClass(const PriorityClass& aOther); - PriorityClass& operator=(const PriorityClass& aOther); - - ProcessPriority Priority() - { - return mPriority; - } - - int32_t OomScoreAdj() - { - return clamped<int32_t>(mOomScoreAdj, OOM_SCORE_ADJ_MIN, OOM_SCORE_ADJ_MAX); - } - - int32_t KillUnderKB() - { - return mKillUnderKB; - } - - nsCString CGroup() - { - return mGroup; - } - - /** - * Adds a process to this priority class, this moves the process' PID into - * the associated control group. - * - * @param aPid The PID of the process to be added. - */ - void AddProcess(int aPid); - -private: - ProcessPriority mPriority; - int32_t mOomScoreAdj; - int32_t mKillUnderKB; - int mCpuCGroupProcsFd; - int mMemCGroupProcsFd; - nsCString mGroup; - - /** - * Return a string that identifies where we can find the value of aPref - * that's specific to mPriority. For example, we might return - * "hal.processPriorityManager.gonk.FOREGROUND_HIGH.oomScoreAdjust". - */ - nsCString PriorityPrefName(const char* aPref) - { - return nsPrintfCString("hal.processPriorityManager.gonk.%s.%s", - ProcessPriorityToString(mPriority), aPref); - } - - /** - * Get the full path of the cgroup.procs file associated with the group. - */ - nsCString CpuCGroupProcsFilename() - { - nsCString cgroupName = mGroup; - - /* If mGroup is empty, our cgroup.procs file is the root procs file, - * located at /dev/cpuctl/cgroup.procs. Otherwise our procs file is - * /dev/cpuctl/NAME/cgroup.procs. */ - - if (!mGroup.IsEmpty()) { - cgroupName.AppendLiteral("/"); - } - - return NS_LITERAL_CSTRING("/dev/cpuctl/") + cgroupName + - NS_LITERAL_CSTRING("cgroup.procs"); - } - - nsCString MemCGroupProcsFilename() - { - nsCString cgroupName = mGroup; - - /* If mGroup is empty, our cgroup.procs file is the root procs file, - * located at /sys/fs/cgroup/memory/cgroup.procs. Otherwise our procs - * file is /sys/fs/cgroup/memory/NAME/cgroup.procs. */ - - if (!mGroup.IsEmpty()) { - cgroupName.AppendLiteral("/"); - } - - return NS_LITERAL_CSTRING("/sys/fs/cgroup/memory/") + cgroupName + - NS_LITERAL_CSTRING("cgroup.procs"); - } - - int OpenCpuCGroupProcs() - { - return open(CpuCGroupProcsFilename().get(), O_WRONLY); - } - - int OpenMemCGroupProcs() - { - return open(MemCGroupProcsFilename().get(), O_WRONLY); - } -}; - -/** - * Try to create the cgroup for the given PriorityClass, if it doesn't already - * exist. This essentially implements mkdir -p; that is, we create parent - * cgroups as necessary. The group parameters are also set according to - * the corresponding preferences. - * - * @param aGroup The name of the group. - * @return true if we successfully created the cgroup, or if it already - * exists. Otherwise, return false. - */ -static bool -EnsureCpuCGroupExists(const nsACString &aGroup) -{ - NS_NAMED_LITERAL_CSTRING(kDevCpuCtl, "/dev/cpuctl/"); - NS_NAMED_LITERAL_CSTRING(kSlash, "/"); - - nsAutoCString groupName(aGroup); - HAL_LOG("EnsureCpuCGroupExists for group '%s'", groupName.get()); - - nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups."); - - /* If cgroup is not empty, append the cgroup name and a dot to obtain the - * group specific preferences. */ - if (!aGroup.IsEmpty()) { - prefPrefix += aGroup + NS_LITERAL_CSTRING("."); - } - - nsAutoCString cpuSharesPref(prefPrefix + NS_LITERAL_CSTRING("cpu_shares")); - int cpuShares = Preferences::GetInt(cpuSharesPref.get()); - - nsAutoCString cpuNotifyOnMigratePref(prefPrefix - + NS_LITERAL_CSTRING("cpu_notify_on_migrate")); - int cpuNotifyOnMigrate = Preferences::GetInt(cpuNotifyOnMigratePref.get()); - - // Create mCGroup and its parent directories, as necessary. - nsCString cgroupIter = aGroup + kSlash; - - int32_t offset = 0; - while ((offset = cgroupIter.FindChar('/', offset)) != -1) { - nsAutoCString path = kDevCpuCtl + Substring(cgroupIter, 0, offset); - int rv = mkdir(path.get(), 0744); - - if (rv == -1 && errno != EEXIST) { - HAL_LOG("Could not create the %s control group.", path.get()); - return false; - } - - offset++; - } - HAL_LOG("EnsureCpuCGroupExists created group '%s'", groupName.get()); - - nsAutoCString pathPrefix(kDevCpuCtl + aGroup + kSlash); - nsAutoCString cpuSharesPath(pathPrefix + NS_LITERAL_CSTRING("cpu.shares")); - if (cpuShares && !WriteSysFile(cpuSharesPath.get(), - nsPrintfCString("%d", cpuShares).get())) { - HAL_LOG("Could not set the cpu share for group %s", cpuSharesPath.get()); - return false; - } - - nsAutoCString notifyOnMigratePath(pathPrefix - + NS_LITERAL_CSTRING("cpu.notify_on_migrate")); - if (!WriteSysFile(notifyOnMigratePath.get(), - nsPrintfCString("%d", cpuNotifyOnMigrate).get())) { - HAL_LOG("Could not set the cpu migration notification flag for group %s", - notifyOnMigratePath.get()); - return false; - } - - return true; -} - -static bool -EnsureMemCGroupExists(const nsACString &aGroup) -{ - NS_NAMED_LITERAL_CSTRING(kMemCtl, "/sys/fs/cgroup/memory/"); - NS_NAMED_LITERAL_CSTRING(kSlash, "/"); - - nsAutoCString groupName(aGroup); - HAL_LOG("EnsureMemCGroupExists for group '%s'", groupName.get()); - - nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups."); - - /* If cgroup is not empty, append the cgroup name and a dot to obtain the - * group specific preferences. */ - if (!aGroup.IsEmpty()) { - prefPrefix += aGroup + NS_LITERAL_CSTRING("."); - } - - nsAutoCString memSwappinessPref(prefPrefix + NS_LITERAL_CSTRING("memory_swappiness")); - int memSwappiness = Preferences::GetInt(memSwappinessPref.get()); - - // Create mCGroup and its parent directories, as necessary. - nsCString cgroupIter = aGroup + kSlash; - - int32_t offset = 0; - while ((offset = cgroupIter.FindChar('/', offset)) != -1) { - nsAutoCString path = kMemCtl + Substring(cgroupIter, 0, offset); - int rv = mkdir(path.get(), 0744); - - if (rv == -1 && errno != EEXIST) { - HAL_LOG("Could not create the %s control group.", path.get()); - return false; - } - - offset++; - } - HAL_LOG("EnsureMemCGroupExists created group '%s'", groupName.get()); - - nsAutoCString pathPrefix(kMemCtl + aGroup + kSlash); - nsAutoCString memSwappinessPath(pathPrefix + NS_LITERAL_CSTRING("memory.swappiness")); - if (!WriteSysFile(memSwappinessPath.get(), - nsPrintfCString("%d", memSwappiness).get())) { - HAL_LOG("Could not set the memory.swappiness for group %s", memSwappinessPath.get()); - return false; - } - HAL_LOG("Set memory.swappiness for group %s to %d", memSwappinessPath.get(), memSwappiness); - - return true; -} - -PriorityClass::PriorityClass(ProcessPriority aPriority) - : mPriority(aPriority) - , mOomScoreAdj(0) - , mKillUnderKB(0) - , mCpuCGroupProcsFd(-1) - , mMemCGroupProcsFd(-1) -{ - DebugOnly<nsresult> rv; - - rv = Preferences::GetInt(PriorityPrefName("OomScoreAdjust").get(), - &mOomScoreAdj); - MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing oom_score_adj preference"); - - rv = Preferences::GetInt(PriorityPrefName("KillUnderKB").get(), - &mKillUnderKB); - - rv = Preferences::GetCString(PriorityPrefName("cgroup").get(), &mGroup); - MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing control group preference"); - - if (EnsureCpuCGroupExists(mGroup)) { - mCpuCGroupProcsFd = OpenCpuCGroupProcs(); - } - if (EnsureMemCGroupExists(mGroup)) { - mMemCGroupProcsFd = OpenMemCGroupProcs(); - } -} - -PriorityClass::~PriorityClass() -{ - if (mCpuCGroupProcsFd != -1) { - close(mCpuCGroupProcsFd); - } - if (mMemCGroupProcsFd != -1) { - close(mMemCGroupProcsFd); - } -} - -PriorityClass::PriorityClass(const PriorityClass& aOther) - : mPriority(aOther.mPriority) - , mOomScoreAdj(aOther.mOomScoreAdj) - , mKillUnderKB(aOther.mKillUnderKB) - , mGroup(aOther.mGroup) -{ - mCpuCGroupProcsFd = OpenCpuCGroupProcs(); - mMemCGroupProcsFd = OpenMemCGroupProcs(); -} - -PriorityClass& PriorityClass::operator=(const PriorityClass& aOther) -{ - mPriority = aOther.mPriority; - mOomScoreAdj = aOther.mOomScoreAdj; - mKillUnderKB = aOther.mKillUnderKB; - mGroup = aOther.mGroup; - mCpuCGroupProcsFd = OpenCpuCGroupProcs(); - mMemCGroupProcsFd = OpenMemCGroupProcs(); - return *this; -} - -void PriorityClass::AddProcess(int aPid) -{ - if (mCpuCGroupProcsFd >= 0) { - nsPrintfCString str("%d", aPid); - - if (write(mCpuCGroupProcsFd, str.get(), strlen(str.get())) < 0) { - HAL_ERR("Couldn't add PID %d to the %s cpu control group", aPid, mGroup.get()); - } - } - if (mMemCGroupProcsFd >= 0) { - nsPrintfCString str("%d", aPid); - - if (write(mMemCGroupProcsFd, str.get(), strlen(str.get())) < 0) { - HAL_ERR("Couldn't add PID %d to the %s memory control group", aPid, mGroup.get()); - } - } -} - -/** - * Get the PriorityClass associated with the given ProcessPriority. - * - * If you pass an invalid ProcessPriority value, we return null. - * - * The pointers returned here are owned by GetPriorityClass (don't free them - * yourself). They are guaranteed to stick around until shutdown. - */ -PriorityClass* -GetPriorityClass(ProcessPriority aPriority) -{ - static StaticAutoPtr<nsTArray<PriorityClass>> priorityClasses; - - // Initialize priorityClasses if this is the first time we're running this - // method. - if (!priorityClasses) { - priorityClasses = new nsTArray<PriorityClass>(); - ClearOnShutdown(&priorityClasses); - - for (int32_t i = 0; i < NUM_PROCESS_PRIORITY; i++) { - priorityClasses->AppendElement(PriorityClass(ProcessPriority(i))); - } - } - - if (aPriority < 0 || - static_cast<uint32_t>(aPriority) >= priorityClasses->Length()) { - return nullptr; - } - - return &(*priorityClasses)[aPriority]; -} - -static void -EnsureKernelLowMemKillerParamsSet() -{ - static bool kernelLowMemKillerParamsSet; - if (kernelLowMemKillerParamsSet) { - return; - } - kernelLowMemKillerParamsSet = true; - - HAL_LOG("Setting kernel's low-mem killer parameters."); - - // Set /sys/module/lowmemorykiller/parameters/{adj,minfree,notify_trigger} - // according to our prefs. These files let us tune when the kernel kills - // processes when we're low on memory, and when it notifies us that we're - // running low on available memory. - // - // adj and minfree are both comma-separated lists of integers. If adj="A,B" - // and minfree="X,Y", then the kernel will kill processes with oom_adj - // A or higher once we have fewer than X pages of memory free, and will kill - // processes with oom_adj B or higher once we have fewer than Y pages of - // memory free. - // - // notify_trigger is a single integer. If we set notify_trigger=Z, then - // we'll get notified when there are fewer than Z pages of memory free. (See - // GonkMemoryPressureMonitoring.cpp.) - - // Build the adj and minfree strings. - nsAutoCString adjParams; - nsAutoCString minfreeParams; - - DebugOnly<int32_t> lowerBoundOfNextOomScoreAdj = OOM_SCORE_ADJ_MIN - 1; - DebugOnly<int32_t> lowerBoundOfNextKillUnderKB = 0; - int32_t countOfLowmemorykillerParametersSets = 0; - - long page_size = sysconf(_SC_PAGESIZE); - - for (int i = NUM_PROCESS_PRIORITY - 1; i >= 0; i--) { - // The system doesn't function correctly if we're missing these prefs, so - // crash loudly. - - PriorityClass* pc = GetPriorityClass(static_cast<ProcessPriority>(i)); - - int32_t oomScoreAdj = pc->OomScoreAdj(); - int32_t killUnderKB = pc->KillUnderKB(); - - if (killUnderKB == 0) { - // ProcessPriority values like PROCESS_PRIORITY_FOREGROUND_KEYBOARD, - // which has only OomScoreAdjust but lacks KillUnderMB value, will not - // create new LMK parameters. - continue; - } - - // The LMK in kernel silently malfunctions if we assign the parameters - // in non-increasing order, so we add this assertion here. See bug 887192. - MOZ_ASSERT(oomScoreAdj > lowerBoundOfNextOomScoreAdj); - MOZ_ASSERT(killUnderKB > lowerBoundOfNextKillUnderKB); - - // The LMK in kernel only accept 6 sets of LMK parameters. See bug 914728. - MOZ_ASSERT(countOfLowmemorykillerParametersSets < 6); - - // adj is in oom_adj units. - adjParams.AppendPrintf("%d,", OomAdjOfOomScoreAdj(oomScoreAdj)); - - // minfree is in pages. - minfreeParams.AppendPrintf("%ld,", killUnderKB * 1024 / page_size); - - lowerBoundOfNextOomScoreAdj = oomScoreAdj; - lowerBoundOfNextKillUnderKB = killUnderKB; - countOfLowmemorykillerParametersSets++; - } - - // Strip off trailing commas. - adjParams.Cut(adjParams.Length() - 1, 1); - minfreeParams.Cut(minfreeParams.Length() - 1, 1); - if (!adjParams.IsEmpty() && !minfreeParams.IsEmpty()) { - WriteSysFile("/sys/module/lowmemorykiller/parameters/adj", adjParams.get()); - WriteSysFile("/sys/module/lowmemorykiller/parameters/minfree", - minfreeParams.get()); - } - - // Set the low-memory-notification threshold. - int32_t lowMemNotifyThresholdKB; - if (NS_SUCCEEDED(Preferences::GetInt( - "hal.processPriorityManager.gonk.notifyLowMemUnderKB", - &lowMemNotifyThresholdKB))) { - - // notify_trigger is in pages. - WriteSysFile("/sys/module/lowmemorykiller/parameters/notify_trigger", - nsPrintfCString("%ld", lowMemNotifyThresholdKB * 1024 / page_size).get()); - } - - // Ensure OOM events appear in logcat - RefPtr<OomVictimLogger> oomLogger = new OomVictimLogger(); - nsCOMPtr<nsIObserverService> os = services::GetObserverService(); - if (os) { - os->AddObserver(oomLogger, "ipc:content-shutdown", false); - } -} - -void -SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU) -{ - HAL_LOG("SetProcessPriority(pid=%d, priority=%d, LRU=%u)", - aPid, aPriority, aLRU); - - // If this is the first time SetProcessPriority was called, set the kernel's - // OOM parameters according to our prefs. - // - // We could/should do this on startup instead of waiting for the first - // SetProcessPriorityCall. But in practice, the master process needs to set - // its priority early in the game, so we can reasonably rely on - // SetProcessPriority being called early in startup. - EnsureKernelLowMemKillerParamsSet(); - - PriorityClass* pc = GetPriorityClass(aPriority); - - int oomScoreAdj = pc->OomScoreAdj(); - - RoundOomScoreAdjUpWithLRU(oomScoreAdj, aLRU); - - // We try the newer interface first, and fall back to the older interface - // on failure. - if (!WriteSysFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(), - nsPrintfCString("%d", oomScoreAdj).get())) - { - WriteSysFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(), - nsPrintfCString("%d", OomAdjOfOomScoreAdj(oomScoreAdj)).get()); - } - - HAL_LOG("Assigning pid %d to cgroup %s", aPid, pc->CGroup().get()); - pc->AddProcess(aPid); -} - -static bool -IsValidRealTimePriority(int aValue, int aSchedulePolicy) -{ - return (aValue >= sched_get_priority_min(aSchedulePolicy)) && - (aValue <= sched_get_priority_max(aSchedulePolicy)); -} - -static void -SetThreadNiceValue(pid_t aTid, ThreadPriority aThreadPriority, int aValue) -{ - MOZ_ASSERT(aThreadPriority < NUM_THREAD_PRIORITY); - MOZ_ASSERT(aThreadPriority >= 0); - - HAL_LOG("Setting thread %d to priority level %s; nice level %d", - aTid, ThreadPriorityToString(aThreadPriority), aValue); - int rv = setpriority(PRIO_PROCESS, aTid, aValue); - - if (rv) { - HAL_LOG("Failed to set thread %d to priority level %s; error %s", aTid, - ThreadPriorityToString(aThreadPriority), strerror(errno)); - } -} - -static void -SetRealTimeThreadPriority(pid_t aTid, - ThreadPriority aThreadPriority, - int aValue) -{ - int policy = SCHED_FIFO; - - MOZ_ASSERT(aThreadPriority < NUM_THREAD_PRIORITY); - MOZ_ASSERT(aThreadPriority >= 0); - MOZ_ASSERT(IsValidRealTimePriority(aValue, policy), "Invalid real time priority"); - - // Setting real time priorities requires using sched_setscheduler - HAL_LOG("Setting thread %d to priority level %s; Real Time priority %d, " - "Schedule FIFO", aTid, ThreadPriorityToString(aThreadPriority), - aValue); - sched_param schedParam; - schedParam.sched_priority = aValue; - int rv = sched_setscheduler(aTid, policy, &schedParam); - - if (rv) { - HAL_LOG("Failed to set thread %d to real time priority level %s; error %s", - aTid, ThreadPriorityToString(aThreadPriority), strerror(errno)); - } -} - -/* - * Used to store the nice value adjustments and real time priorities for the - * various thread priority levels. - */ -struct ThreadPriorityPrefs { - bool initialized; - struct { - int nice; - int realTime; - } priorities[NUM_THREAD_PRIORITY]; -}; - -/* - * Reads the preferences for the various process priority levels and sets up - * watchers so that if they're dynamically changed the change is reflected on - * the appropriate variables. - */ -void -EnsureThreadPriorityPrefs(ThreadPriorityPrefs* prefs) -{ - if (prefs->initialized) { - return; - } - - for (int i = THREAD_PRIORITY_COMPOSITOR; i < NUM_THREAD_PRIORITY; i++) { - ThreadPriority priority = static_cast<ThreadPriority>(i); - - // Read the nice values - const char* threadPriorityStr = ThreadPriorityToString(priority); - nsPrintfCString niceStr("hal.gonk.%s.nice", threadPriorityStr); - Preferences::AddIntVarCache(&prefs->priorities[i].nice, niceStr.get()); - - // Read the real-time priorities - nsPrintfCString realTimeStr("hal.gonk.%s.rt_priority", threadPriorityStr); - Preferences::AddIntVarCache(&prefs->priorities[i].realTime, - realTimeStr.get()); - } - - prefs->initialized = true; -} - -static void -DoSetThreadPriority(pid_t aTid, hal::ThreadPriority aThreadPriority) -{ - // See bug 999115, we can only read preferences on the main thread otherwise - // we create a race condition in HAL - MOZ_ASSERT(NS_IsMainThread(), "Can only set thread priorities on main thread"); - MOZ_ASSERT(aThreadPriority >= 0); - - static ThreadPriorityPrefs prefs = { 0 }; - EnsureThreadPriorityPrefs(&prefs); - - switch (aThreadPriority) { - case THREAD_PRIORITY_COMPOSITOR: - break; - default: - HAL_ERR("Unrecognized thread priority %d; Doing nothing", - aThreadPriority); - return; - } - - int realTimePriority = prefs.priorities[aThreadPriority].realTime; - - if (IsValidRealTimePriority(realTimePriority, SCHED_FIFO)) { - SetRealTimeThreadPriority(aTid, aThreadPriority, realTimePriority); - return; - } - - SetThreadNiceValue(aTid, aThreadPriority, - prefs.priorities[aThreadPriority].nice); -} - -namespace { - -/** - * This class sets the priority of threads given the kernel thread's id and a - * value taken from hal::ThreadPriority. - * - * This runnable must always be dispatched to the main thread otherwise it will fail. - * We have to run this from the main thread since preferences can only be read on - * main thread. - */ -class SetThreadPriorityRunnable : public Runnable -{ -public: - SetThreadPriorityRunnable(pid_t aThreadId, hal::ThreadPriority aThreadPriority) - : mThreadId(aThreadId) - , mThreadPriority(aThreadPriority) - { } - - NS_IMETHOD Run() override - { - NS_ASSERTION(NS_IsMainThread(), "Can only set thread priorities on main thread"); - hal_impl::DoSetThreadPriority(mThreadId, mThreadPriority); - return NS_OK; - } - -private: - pid_t mThreadId; - hal::ThreadPriority mThreadPriority; -}; - -} // namespace - -void -SetCurrentThreadPriority(ThreadPriority aThreadPriority) -{ - pid_t threadId = gettid(); - hal_impl::SetThreadPriority(threadId, aThreadPriority); -} - -void -SetThreadPriority(PlatformThreadId aThreadId, - ThreadPriority aThreadPriority) -{ - switch (aThreadPriority) { - case THREAD_PRIORITY_COMPOSITOR: { - nsCOMPtr<nsIRunnable> runnable = - new SetThreadPriorityRunnable(aThreadId, aThreadPriority); - NS_DispatchToMainThread(runnable); - break; - } - default: - HAL_LOG("Unrecognized thread priority %d; Doing nothing", - aThreadPriority); - return; - } -} - -void -FactoryReset(FactoryResetReason& aReason) -{ - nsCOMPtr<nsIRecoveryService> recoveryService = - do_GetService("@mozilla.org/recovery-service;1"); - if (!recoveryService) { - NS_WARNING("Could not get recovery service!"); - return; - } - - if (aReason == FactoryResetReason::Wipe) { - recoveryService->FactoryReset("wipe"); - } else if (aReason == FactoryResetReason::Root) { - recoveryService->FactoryReset("root"); - } else { - recoveryService->FactoryReset("normal"); - } -} - -} // hal_impl -} // mozilla diff --git a/hal/gonk/GonkSensor.cpp b/hal/gonk/GonkSensor.cpp deleted file mode 100644 index 7bd2d3c9b..000000000 --- a/hal/gonk/GonkSensor.cpp +++ /dev/null @@ -1,861 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <pthread.h> -#include <stdio.h> - -#include "mozilla/DebugOnly.h" -#include "mozilla/Saturate.h" - -#include "base/basictypes.h" -#include "base/thread.h" -#include "base/task.h" - -#include "GonkSensorsInterface.h" -#include "GonkSensorsPollInterface.h" -#include "GonkSensorsRegistryInterface.h" -#include "Hal.h" -#include "HalLog.h" -#include "HalSensor.h" -#include "hardware/sensors.h" -#include "nsThreadUtils.h" - -using namespace mozilla::hal; - -namespace mozilla { - -// -// Internal implementation -// - -// The value from SensorDevice.h (Android) -#define DEFAULT_DEVICE_POLL_RATE 200000000 /*200ms*/ -// ProcessOrientation.cpp needs smaller poll rate to detect delay between -// different orientation angles -#define ACCELEROMETER_POLL_RATE 66667000 /*66.667ms*/ - -// This is present in Android from API level 18 onwards, which is 4.3. We might -// be building on something before 4.3, so use a local define for its value -#define MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR 15 - -double radToDeg(double a) { - return a * (180.0 / M_PI); -} - -static SensorType -HardwareSensorToHalSensor(int type) -{ - switch(type) { - case SENSOR_TYPE_ORIENTATION: - return SENSOR_ORIENTATION; - case SENSOR_TYPE_ACCELEROMETER: - return SENSOR_ACCELERATION; - case SENSOR_TYPE_PROXIMITY: - return SENSOR_PROXIMITY; - case SENSOR_TYPE_LIGHT: - return SENSOR_LIGHT; - case SENSOR_TYPE_GYROSCOPE: - return SENSOR_GYROSCOPE; - case SENSOR_TYPE_LINEAR_ACCELERATION: - return SENSOR_LINEAR_ACCELERATION; - case SENSOR_TYPE_ROTATION_VECTOR: - return SENSOR_ROTATION_VECTOR; - case MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR: - return SENSOR_GAME_ROTATION_VECTOR; - default: - return SENSOR_UNKNOWN; - } -} - -static SensorAccuracyType -HardwareStatusToHalAccuracy(int status) { - return static_cast<SensorAccuracyType>(status); -} - -static int -HalSensorToHardwareSensor(SensorType type) -{ - switch(type) { - case SENSOR_ORIENTATION: - return SENSOR_TYPE_ORIENTATION; - case SENSOR_ACCELERATION: - return SENSOR_TYPE_ACCELEROMETER; - case SENSOR_PROXIMITY: - return SENSOR_TYPE_PROXIMITY; - case SENSOR_LIGHT: - return SENSOR_TYPE_LIGHT; - case SENSOR_GYROSCOPE: - return SENSOR_TYPE_GYROSCOPE; - case SENSOR_LINEAR_ACCELERATION: - return SENSOR_TYPE_LINEAR_ACCELERATION; - case SENSOR_ROTATION_VECTOR: - return SENSOR_TYPE_ROTATION_VECTOR; - case SENSOR_GAME_ROTATION_VECTOR: - return MOZ_SENSOR_TYPE_GAME_ROTATION_VECTOR; - default: - return -1; - } -} - -static int -SensorseventStatus(const sensors_event_t& data) -{ - int type = data.type; - switch(type) { - case SENSOR_ORIENTATION: - return data.orientation.status; - case SENSOR_LINEAR_ACCELERATION: - case SENSOR_ACCELERATION: - return data.acceleration.status; - case SENSOR_GYROSCOPE: - return data.gyro.status; - } - - return SENSOR_STATUS_UNRELIABLE; -} - -class SensorRunnable : public Runnable -{ -public: - SensorRunnable(const sensors_event_t& data, const sensor_t* sensors, ssize_t size) - { - mSensorData.sensor() = HardwareSensorToHalSensor(data.type); - mSensorData.accuracy() = HardwareStatusToHalAccuracy(SensorseventStatus(data)); - mSensorData.timestamp() = data.timestamp; - if (mSensorData.sensor() == SENSOR_GYROSCOPE) { - // libhardware returns gyro as rad. convert. - mSensorValues.AppendElement(radToDeg(data.data[0])); - mSensorValues.AppendElement(radToDeg(data.data[1])); - mSensorValues.AppendElement(radToDeg(data.data[2])); - } else if (mSensorData.sensor() == SENSOR_PROXIMITY) { - mSensorValues.AppendElement(data.data[0]); - mSensorValues.AppendElement(0); - - // Determine the maxRange for this sensor. - for (ssize_t i = 0; i < size; i++) { - if (sensors[i].type == SENSOR_TYPE_PROXIMITY) { - mSensorValues.AppendElement(sensors[i].maxRange); - } - } - } else if (mSensorData.sensor() == SENSOR_LIGHT) { - mSensorValues.AppendElement(data.data[0]); - } else if (mSensorData.sensor() == SENSOR_ROTATION_VECTOR) { - mSensorValues.AppendElement(data.data[0]); - mSensorValues.AppendElement(data.data[1]); - mSensorValues.AppendElement(data.data[2]); - if (data.data[3] == 0.0) { - // data.data[3] was optional in Android <= API level 18. It can be computed from 012, - // but it's better to take the actual value if one is provided. The computation is - // v = 1 - d[0]*d[0] - d[1]*d[1] - d[2]*d[2] - // d[3] = v > 0 ? sqrt(v) : 0; - // I'm assuming that it will be 0 if it's not passed in. (The values form a unit - // quaternion, so the angle can be computed from the direction vector.) - float sx = data.data[0], sy = data.data[1], sz = data.data[2]; - float v = 1.0f - sx*sx - sy*sy - sz*sz; - mSensorValues.AppendElement(v > 0.0f ? sqrt(v) : 0.0f); - } else { - mSensorValues.AppendElement(data.data[3]); - } - } else if (mSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) { - mSensorValues.AppendElement(data.data[0]); - mSensorValues.AppendElement(data.data[1]); - mSensorValues.AppendElement(data.data[2]); - mSensorValues.AppendElement(data.data[3]); - } else { - mSensorValues.AppendElement(data.data[0]); - mSensorValues.AppendElement(data.data[1]); - mSensorValues.AppendElement(data.data[2]); - } - mSensorData.values() = mSensorValues; - } - - ~SensorRunnable() {} - - NS_IMETHOD Run() override - { - NotifySensorChange(mSensorData); - return NS_OK; - } - -private: - SensorData mSensorData; - AutoTArray<float, 4> mSensorValues; -}; - -namespace hal_impl { - -static DebugOnly<int> sSensorRefCount[NUM_SENSOR_TYPE]; -static base::Thread* sPollingThread; -static sensors_poll_device_t* sSensorDevice; -static sensors_module_t* sSensorModule; - -static void -PollSensors() -{ - const size_t numEventMax = 16; - sensors_event_t buffer[numEventMax]; - const sensor_t* sensors; - int size = sSensorModule->get_sensors_list(sSensorModule, &sensors); - - do { - // didn't check sSensorDevice because already be done on creating pollingThread. - int n = sSensorDevice->poll(sSensorDevice, buffer, numEventMax); - if (n < 0) { - HAL_ERR("Error polling for sensor data (err=%d)", n); - break; - } - - for (int i = 0; i < n; ++i) { - // FIXME: bug 802004, add proper support for the magnetic field sensor. - if (buffer[i].type == SENSOR_TYPE_MAGNETIC_FIELD) - continue; - - // Bug 938035, transfer HAL data for orientation sensor to meet w3c spec - // ex: HAL report alpha=90 means East but alpha=90 means West in w3c spec - if (buffer[i].type == SENSOR_TYPE_ORIENTATION) { - buffer[i].orientation.azimuth = 360 - buffer[i].orientation.azimuth; - buffer[i].orientation.pitch = -buffer[i].orientation.pitch; - buffer[i].orientation.roll = -buffer[i].orientation.roll; - } - - if (HardwareSensorToHalSensor(buffer[i].type) == SENSOR_UNKNOWN) { - // Emulator is broken and gives us events without types set - int index; - for (index = 0; index < size; index++) { - if (sensors[index].handle == buffer[i].sensor) { - break; - } - } - if (index < size && - HardwareSensorToHalSensor(sensors[index].type) != SENSOR_UNKNOWN) { - buffer[i].type = sensors[index].type; - } else { - HAL_LOG("Could not determine sensor type of event"); - continue; - } - } - - NS_DispatchToMainThread(new SensorRunnable(buffer[i], sensors, size)); - } - } while (true); -} - -static void -SwitchSensor(bool aActivate, sensor_t aSensor, pthread_t aThreadId) -{ - int index = HardwareSensorToHalSensor(aSensor.type); - - MOZ_ASSERT(sSensorRefCount[index] || aActivate); - - sSensorDevice->activate(sSensorDevice, aSensor.handle, aActivate); - - if (aActivate) { - if (aSensor.type == SENSOR_TYPE_ACCELEROMETER) { - sSensorDevice->setDelay(sSensorDevice, aSensor.handle, - ACCELEROMETER_POLL_RATE); - } else { - sSensorDevice->setDelay(sSensorDevice, aSensor.handle, - DEFAULT_DEVICE_POLL_RATE); - } - } - - if (aActivate) { - sSensorRefCount[index]++; - } else { - sSensorRefCount[index]--; - } -} - -static void -SetSensorState(SensorType aSensor, bool activate) -{ - int type = HalSensorToHardwareSensor(aSensor); - const sensor_t* sensors = nullptr; - - int size = sSensorModule->get_sensors_list(sSensorModule, &sensors); - for (ssize_t i = 0; i < size; i++) { - if (sensors[i].type == type) { - SwitchSensor(activate, sensors[i], pthread_self()); - break; - } - } -} - -static void -EnableSensorNotificationsInternal(SensorType aSensor) -{ - if (!sSensorModule) { - hw_get_module(SENSORS_HARDWARE_MODULE_ID, - (hw_module_t const**)&sSensorModule); - if (!sSensorModule) { - HAL_ERR("Can't get sensor HAL module\n"); - return; - } - - sensors_open(&sSensorModule->common, &sSensorDevice); - if (!sSensorDevice) { - sSensorModule = nullptr; - HAL_ERR("Can't get sensor poll device from module \n"); - return; - } - - sensor_t const* sensors; - int count = sSensorModule->get_sensors_list(sSensorModule, &sensors); - for (size_t i=0 ; i<size_t(count) ; i++) { - sSensorDevice->activate(sSensorDevice, sensors[i].handle, 0); - } - } - - if (!sPollingThread) { - sPollingThread = new base::Thread("GonkSensors"); - MOZ_ASSERT(sPollingThread); - // sPollingThread never terminates because poll may never return - sPollingThread->Start(); - sPollingThread->message_loop()->PostTask( - NewRunnableFunction(PollSensors)); - } - - SetSensorState(aSensor, true); -} - -static void -DisableSensorNotificationsInternal(SensorType aSensor) -{ - if (!sSensorModule) { - return; - } - SetSensorState(aSensor, false); -} - -// -// Daemon -// - -typedef detail::SaturateOp<uint32_t> SaturateOpUint32; - -/** - * The poll notification handler receives all events about sensors and - * sensor events. - */ -class SensorsPollNotificationHandler final - : public GonkSensorsPollNotificationHandler -{ -public: - SensorsPollNotificationHandler(GonkSensorsPollInterface* aPollInterface) - : mPollInterface(aPollInterface) - { - MOZ_ASSERT(mPollInterface); - - mPollInterface->SetNotificationHandler(this); - } - - void EnableSensorsByType(SensorsType aType) - { - if (SaturateOpUint32(mClasses[aType].mActivated)++) { - return; - } - - SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType); - - // Old ref-count for the sensor type was 0, so we - // activate all sensors of the type. - for (size_t i = 0; i < mSensors.Length(); ++i) { - if (mSensors[i].mType == aType && - mSensors[i].mDeliveryMode == deliveryMode) { - mPollInterface->EnableSensor(mSensors[i].mId, nullptr); - mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType), - nullptr); - } - } - } - - void DisableSensorsByType(SensorsType aType) - { - if (SaturateOpUint32(mClasses[aType].mActivated)-- != 1) { - return; - } - - SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType); - - // Old ref-count for the sensor type was 1, so we - // deactivate all sensors of the type. - for (size_t i = 0; i < mSensors.Length(); ++i) { - if (mSensors[i].mType == aType && - mSensors[i].mDeliveryMode == deliveryMode) { - mPollInterface->DisableSensor(mSensors[i].mId, nullptr); - } - } - } - - void ClearSensorClasses() - { - for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mClasses); ++i) { - mClasses[i] = SensorsSensorClass(); - } - } - - void ClearSensors() - { - mSensors.Clear(); - } - - // Methods for SensorsPollNotificationHandler - // - - void ErrorNotification(SensorsError aError) override - { - // XXX: Bug 1206056: Try to repair some of the errors or restart cleanly. - } - - void SensorDetectedNotification(int32_t aId, SensorsType aType, - float aRange, float aResolution, - float aPower, int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode) override - { - auto i = FindSensorIndexById(aId); - if (i == -1) { - // Add a new sensor... - i = mSensors.Length(); - mSensors.AppendElement(SensorsSensor(aId, aType, aRange, aResolution, - aPower, aMinPeriod, aMaxPeriod, - aTriggerMode, aDeliveryMode)); - } else { - // ...or update an existing one. - mSensors[i] = SensorsSensor(aId, aType, aRange, aResolution, aPower, - aMinPeriod, aMaxPeriod, aTriggerMode, - aDeliveryMode); - } - - mClasses[aType].UpdateFromSensor(mSensors[i]); - - if (mClasses[aType].mActivated && - mSensors[i].mDeliveryMode == DefaultSensorsDeliveryMode(aType)) { - // The new sensor's type is enabled, so enable sensor. - mPollInterface->EnableSensor(aId, nullptr); - mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType), - nullptr); - } - } - - void SensorLostNotification(int32_t aId) override - { - auto i = FindSensorIndexById(aId); - if (i != -1) { - mSensors.RemoveElementAt(i); - } - } - - void EventNotification(int32_t aId, const SensorsEvent& aEvent) override - { - auto i = FindSensorIndexById(aId); - if (i == -1) { - HAL_ERR("Sensor %d not registered", aId); - return; - } - - SensorData sensorData; - auto rv = CreateSensorData(aEvent, mClasses[mSensors[i].mType], - sensorData); - if (NS_FAILED(rv)) { - return; - } - - NotifySensorChange(sensorData); - } - -private: - ssize_t FindSensorIndexById(int32_t aId) const - { - for (size_t i = 0; i < mSensors.Length(); ++i) { - if (mSensors[i].mId == aId) { - return i; - } - } - return -1; - } - - uint64_t DefaultSensorPeriod(SensorsType aType) const - { - return aType == SENSORS_TYPE_ACCELEROMETER ? ACCELEROMETER_POLL_RATE - : DEFAULT_DEVICE_POLL_RATE; - } - - SensorsDeliveryMode DefaultSensorsDeliveryMode(SensorsType aType) const - { - if (aType == SENSORS_TYPE_PROXIMITY || - aType == SENSORS_TYPE_SIGNIFICANT_MOTION) { - return SENSORS_DELIVERY_MODE_IMMEDIATE; - } - return SENSORS_DELIVERY_MODE_BEST_EFFORT; - } - - SensorType HardwareSensorToHalSensor(SensorsType aType) const - { - // FIXME: bug 802004, add proper support for the magnetic-field sensor. - switch (aType) { - case SENSORS_TYPE_ORIENTATION: - return SENSOR_ORIENTATION; - case SENSORS_TYPE_ACCELEROMETER: - return SENSOR_ACCELERATION; - case SENSORS_TYPE_PROXIMITY: - return SENSOR_PROXIMITY; - case SENSORS_TYPE_LIGHT: - return SENSOR_LIGHT; - case SENSORS_TYPE_GYROSCOPE: - return SENSOR_GYROSCOPE; - case SENSORS_TYPE_LINEAR_ACCELERATION: - return SENSOR_LINEAR_ACCELERATION; - case SENSORS_TYPE_ROTATION_VECTOR: - return SENSOR_ROTATION_VECTOR; - case SENSORS_TYPE_GAME_ROTATION_VECTOR: - return SENSOR_GAME_ROTATION_VECTOR; - default: - NS_NOTREACHED("Invalid sensors type"); - } - return SENSOR_UNKNOWN; - } - - SensorAccuracyType HardwareStatusToHalAccuracy(SensorsStatus aStatus) const - { - return static_cast<SensorAccuracyType>(aStatus - 1); - } - - nsresult CreateSensorData(const SensorsEvent& aEvent, - const SensorsSensorClass& aSensorClass, - SensorData& aSensorData) const - { - AutoTArray<float, 4> sensorValues; - - auto sensor = HardwareSensorToHalSensor(aEvent.mType); - - if (sensor == SENSOR_UNKNOWN) { - return NS_ERROR_ILLEGAL_VALUE; - } - - aSensorData.sensor() = sensor; - aSensorData.accuracy() = HardwareStatusToHalAccuracy(aEvent.mStatus); - aSensorData.timestamp() = aEvent.mTimestamp; - - if (aSensorData.sensor() == SENSOR_ORIENTATION) { - // Bug 938035: transfer HAL data for orientation sensor to meet W3C spec - // ex: HAL report alpha=90 means East but alpha=90 means West in W3C spec - sensorValues.AppendElement(360.0 - radToDeg(aEvent.mData.mFloat[0])); - sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[1])); - sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[2])); - } else if (aSensorData.sensor() == SENSOR_ACCELERATION) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - } else if (aSensorData.sensor() == SENSOR_PROXIMITY) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aSensorClass.mMinValue); - sensorValues.AppendElement(aSensorClass.mMaxValue); - } else if (aSensorData.sensor() == SENSOR_LINEAR_ACCELERATION) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - } else if (aSensorData.sensor() == SENSOR_GYROSCOPE) { - sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[0])); - sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[1])); - sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[2])); - } else if (aSensorData.sensor() == SENSOR_LIGHT) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - } else if (aSensorData.sensor() == SENSOR_ROTATION_VECTOR) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - sensorValues.AppendElement(aEvent.mData.mFloat[3]); - } else if (aSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - sensorValues.AppendElement(aEvent.mData.mFloat[3]); - } - - aSensorData.values() = sensorValues; - - return NS_OK; - } - - GonkSensorsPollInterface* mPollInterface; - nsTArray<SensorsSensor> mSensors; - SensorsSensorClass mClasses[SENSORS_NUM_TYPES]; -}; - -static StaticAutoPtr<SensorsPollNotificationHandler> sPollNotificationHandler; - -/** - * This is the notifiaction handler for the Sensors interface. If the backend - * crashes, we can restart it from here. - */ -class SensorsNotificationHandler final : public GonkSensorsNotificationHandler -{ -public: - SensorsNotificationHandler(GonkSensorsInterface* aInterface) - : mInterface(aInterface) - { - MOZ_ASSERT(mInterface); - - mInterface->SetNotificationHandler(this); - } - - void BackendErrorNotification(bool aCrashed) override - { - // XXX: Bug 1206056: restart sensorsd - } - -private: - GonkSensorsInterface* mInterface; -}; - -static StaticAutoPtr<SensorsNotificationHandler> sNotificationHandler; - -/** - * |SensorsRegisterModuleResultHandler| implements the result-handler - * callback for registering the Poll service and activating the first - * sensors. If an error occures during the process, the result handler - * disconnects and closes the backend. - */ -class SensorsRegisterModuleResultHandler final - : public GonkSensorsRegistryResultHandler -{ -public: - SensorsRegisterModuleResultHandler( - uint32_t* aSensorsTypeActivated, - GonkSensorsInterface* aInterface) - : mSensorsTypeActivated(aSensorsTypeActivated) - , mInterface(aInterface) - { - MOZ_ASSERT(mSensorsTypeActivated); - MOZ_ASSERT(mInterface); - } - void OnError(SensorsError aError) override - { - GonkSensorsRegistryResultHandler::OnError(aError); // print error message - Disconnect(); // Registering failed, so close the connection completely - } - void RegisterModule(uint32_t aProtocolVersion) override - { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!sPollNotificationHandler); - - // Init, step 3: set notification handler for poll service and vice versa - auto pollInterface = mInterface->GetSensorsPollInterface(); - if (!pollInterface) { - Disconnect(); - return; - } - if (NS_FAILED(pollInterface->SetProtocolVersion(aProtocolVersion))) { - Disconnect(); - return; - } - - sPollNotificationHandler = - new SensorsPollNotificationHandler(pollInterface); - - // Init, step 4: activate sensors - for (int i = 0; i < SENSORS_NUM_TYPES; ++i) { - while (mSensorsTypeActivated[i]) { - sPollNotificationHandler->EnableSensorsByType( - static_cast<SensorsType>(i)); - --mSensorsTypeActivated[i]; - } - } - } -public: - void Disconnect() - { - class DisconnectResultHandler final : public GonkSensorsResultHandler - { - public: - void OnError(SensorsError aError) - { - GonkSensorsResultHandler::OnError(aError); // print error message - sNotificationHandler = nullptr; - } - void Disconnect() override - { - sNotificationHandler = nullptr; - } - }; - mInterface->Disconnect(new DisconnectResultHandler()); - } -private: - uint32_t* mSensorsTypeActivated; - GonkSensorsInterface* mInterface; -}; - -/** - * |SensorsConnectResultHandler| implements the result-handler - * callback for starting the Sensors backend. - */ -class SensorsConnectResultHandler final : public GonkSensorsResultHandler -{ -public: - SensorsConnectResultHandler( - uint32_t* aSensorsTypeActivated, - GonkSensorsInterface* aInterface) - : mSensorsTypeActivated(aSensorsTypeActivated) - , mInterface(aInterface) - { - MOZ_ASSERT(mSensorsTypeActivated); - MOZ_ASSERT(mInterface); - } - void OnError(SensorsError aError) override - { - GonkSensorsResultHandler::OnError(aError); // print error message - sNotificationHandler = nullptr; - } - void Connect() override - { - MOZ_ASSERT(NS_IsMainThread()); - - // Init, step 2: register poll service - auto registryInterface = mInterface->GetSensorsRegistryInterface(); - if (!registryInterface) { - return; - } - registryInterface->RegisterModule( - GonkSensorsPollModule::SERVICE_ID, - new SensorsRegisterModuleResultHandler(mSensorsTypeActivated, - mInterface)); - } -private: - uint32_t* mSensorsTypeActivated; - GonkSensorsInterface* mInterface; -}; - -static uint32_t sSensorsTypeActivated[SENSORS_NUM_TYPES]; - -static const SensorsType sSensorsType[] = { - [SENSOR_ORIENTATION] = SENSORS_TYPE_ORIENTATION, - [SENSOR_ACCELERATION] = SENSORS_TYPE_ACCELEROMETER, - [SENSOR_PROXIMITY] = SENSORS_TYPE_PROXIMITY, - [SENSOR_LINEAR_ACCELERATION] = SENSORS_TYPE_LINEAR_ACCELERATION, - [SENSOR_GYROSCOPE] = SENSORS_TYPE_GYROSCOPE, - [SENSOR_LIGHT] = SENSORS_TYPE_LIGHT, - [SENSOR_ROTATION_VECTOR] = SENSORS_TYPE_ROTATION_VECTOR, - [SENSOR_GAME_ROTATION_VECTOR] = SENSORS_TYPE_GAME_ROTATION_VECTOR -}; - -void -EnableSensorNotificationsDaemon(SensorType aSensor) -{ - if ((aSensor < 0) || - (aSensor > static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sSensorsType)))) { - HAL_ERR("Sensor type %d not known", aSensor); - return; // Unsupported sensor type - } - - auto interface = GonkSensorsInterface::GetInstance(); - if (!interface) { - return; - } - - if (sPollNotificationHandler) { - // Everythings already up and running; enable sensor type. - sPollNotificationHandler->EnableSensorsByType(sSensorsType[aSensor]); - return; - } - - ++SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]); - - if (sNotificationHandler) { - // We are in the middle of a pending start up; nothing else to do. - return; - } - - // Start up - - MOZ_ASSERT(!sPollNotificationHandler); - MOZ_ASSERT(!sNotificationHandler); - - sNotificationHandler = new SensorsNotificationHandler(interface); - - // Init, step 1: connect to Sensors backend - interface->Connect( - sNotificationHandler, - new SensorsConnectResultHandler(sSensorsTypeActivated, interface)); -} - -void -DisableSensorNotificationsDaemon(SensorType aSensor) -{ - if ((aSensor < 0) || - (aSensor > static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sSensorsType)))) { - HAL_ERR("Sensor type %d not known", aSensor); - return; // Unsupported sensor type - } - - if (sPollNotificationHandler) { - // Everthings up and running; disable sensors type - sPollNotificationHandler->DisableSensorsByType(sSensorsType[aSensor]); - return; - } - - // We might be in the middle of a startup; decrement type's ref-counter. - --SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]); - - // TODO: stop sensorsd if all sensors are disabled -} - -// -// Public interface -// - -// TODO: Remove in-Gecko sensors code. Until all devices' base -// images come with sensorsd installed, we have to support the -// in-Gecko implementation as well. So we test for the existance -// of the binary. If it's there, we use it. Otherwise we run the -// old code. -static bool -HasDaemon() -{ - static bool tested; - static bool hasDaemon; - - if (MOZ_UNLIKELY(!tested)) { - hasDaemon = !access("/system/bin/sensorsd", X_OK); - tested = true; - } - - return hasDaemon; -} - -void -EnableSensorNotifications(SensorType aSensor) -{ - if (HasDaemon()) { - EnableSensorNotificationsDaemon(aSensor); - } else { - EnableSensorNotificationsInternal(aSensor); - } -} - -void -DisableSensorNotifications(SensorType aSensor) -{ - if (HasDaemon()) { - DisableSensorNotificationsDaemon(aSensor); - } else { - DisableSensorNotificationsInternal(aSensor); - } -} - -} // hal_impl -} // mozilla diff --git a/hal/gonk/GonkSensorsHelpers.cpp b/hal/gonk/GonkSensorsHelpers.cpp deleted file mode 100644 index ccc940c7c..000000000 --- a/hal/gonk/GonkSensorsHelpers.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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 "GonkSensorsHelpers.h" - -namespace mozilla { -namespace hal { - -// -// Unpacking -// - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut) -{ - nsresult rv = UnpackPDU(aPDU, aOut.mType); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mTimestamp); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mStatus); - if (NS_FAILED(rv)) { - return rv; - } - - size_t i = 0; - - switch (aOut.mType) { - case SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED: - case SENSORS_TYPE_GYROSCOPE_UNCALIBRATED: - /* 6 data values */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - /* fall through */ - case SENSORS_TYPE_ROTATION_VECTOR: - case SENSORS_TYPE_GAME_ROTATION_VECTOR: - case SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR: - /* 5 data values */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - /* fall through */ - case SENSORS_TYPE_ACCELEROMETER: - case SENSORS_TYPE_GEOMAGNETIC_FIELD: - case SENSORS_TYPE_ORIENTATION: - case SENSORS_TYPE_GYROSCOPE: - case SENSORS_TYPE_GRAVITY: - case SENSORS_TYPE_LINEAR_ACCELERATION: - /* 3 data values */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - /* fall through */ - case SENSORS_TYPE_LIGHT: - case SENSORS_TYPE_PRESSURE: - case SENSORS_TYPE_TEMPERATURE: - case SENSORS_TYPE_PROXIMITY: - case SENSORS_TYPE_RELATIVE_HUMIDITY: - case SENSORS_TYPE_AMBIENT_TEMPERATURE: - case SENSORS_TYPE_HEART_RATE: - case SENSORS_TYPE_TILT_DETECTOR: - case SENSORS_TYPE_WAKE_GESTURE: - case SENSORS_TYPE_GLANCE_GESTURE: - case SENSORS_TYPE_PICK_UP_GESTURE: - case SENSORS_TYPE_WRIST_TILT_GESTURE: - case SENSORS_TYPE_SIGNIFICANT_MOTION: - case SENSORS_TYPE_STEP_DETECTED: - /* 1 data value */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - break; - case SENSORS_TYPE_STEP_COUNTER: - /* 1 data value */ - rv = UnpackPDU(aPDU, aOut.mData.mUint[0]); - if (NS_FAILED(rv)) { - return rv; - } - break; - default: - if (MOZ_HAL_IPC_UNPACK_WARN_IF(true, SensorsEvent)) { - return NS_ERROR_ILLEGAL_VALUE; - } - } - rv = UnpackPDU(aPDU, aOut.mDeliveryMode); - if (NS_FAILED(rv)) { - return rv; - } - return NS_OK; -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsHelpers.h b/hal/gonk/GonkSensorsHelpers.h deleted file mode 100644 index 5218af53a..000000000 --- a/hal/gonk/GonkSensorsHelpers.h +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#ifndef hal_gonk_GonkSensorsHelpers_h -#define hal_gonk_GonkSensorsHelpers_h - -#include <mozilla/ipc/DaemonSocketPDU.h> -#include <mozilla/ipc/DaemonSocketPDUHelpers.h> -#include "SensorsTypes.h" - -namespace mozilla { -namespace hal { - -using mozilla::ipc::DaemonSocketPDU; -using mozilla::ipc::DaemonSocketPDUHeader; -using mozilla::ipc::DaemonSocketPDUHelpers::Convert; -using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU; -using mozilla::ipc::DaemonSocketPDUHelpers::UnpackPDU; - -using namespace mozilla::ipc::DaemonSocketPDUHelpers; - -// -// Conversion -// -// The functions below convert the input value to the output value's -// type and perform extension tests on the validity of the result. On -// success the output value will be returned in |aOut|. The functions -// return NS_OK on success, or an XPCOM error code otherwise. -// -// See the documentation of the HAL IPC framework for more information -// on conversion functions. -// - -nsresult -Convert(int32_t aIn, SensorsStatus& aOut) -{ - static const uint8_t sStatus[] = { - [0] = SENSORS_STATUS_NO_CONTACT, // '-1' - [1] = SENSORS_STATUS_UNRELIABLE, // '0' - [2] = SENSORS_STATUS_ACCURACY_LOW, // '1' - [3] = SENSORS_STATUS_ACCURACY_MEDIUM, // '2' - [4] = SENSORS_STATUS_ACCURACY_HIGH // '3' - }; - static const int8_t sOffset = -1; // '-1' is the lower bound of the status - - if (MOZ_HAL_IPC_CONVERT_WARN_IF(aIn < sOffset, int32_t, SensorsStatus) || - MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= (static_cast<ssize_t>(MOZ_ARRAY_LENGTH(sStatus)) + sOffset), - int32_t, SensorsStatus)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast<SensorsStatus>(sStatus[aIn - sOffset]); - return NS_OK; -} - -nsresult -Convert(uint8_t aIn, SensorsDeliveryMode& aOut) -{ - static const uint8_t sMode[] = { - [0x00] = SENSORS_DELIVERY_MODE_BEST_EFFORT, - [0x01] = SENSORS_DELIVERY_MODE_IMMEDIATE - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsDeliveryMode)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast<SensorsDeliveryMode>(sMode[aIn]); - return NS_OK; -} - -nsresult -Convert(uint8_t aIn, SensorsError& aOut) -{ - static const uint8_t sError[] = { - [0x00] = SENSORS_ERROR_NONE, - [0x01] = SENSORS_ERROR_FAIL, - [0x02] = SENSORS_ERROR_NOT_READY, - [0x03] = SENSORS_ERROR_NOMEM, - [0x04] = SENSORS_ERROR_BUSY, - [0x05] = SENSORS_ERROR_DONE, - [0x06] = SENSORS_ERROR_UNSUPPORTED, - [0x07] = SENSORS_ERROR_PARM_INVALID - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sError), uint8_t, SensorsError)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast<SensorsError>(sError[aIn]); - return NS_OK; -} - -nsresult -Convert(uint8_t aIn, SensorsTriggerMode& aOut) -{ - static const uint8_t sMode[] = { - [0x00] = SENSORS_TRIGGER_MODE_CONTINUOUS, - [0x01] = SENSORS_TRIGGER_MODE_ON_CHANGE, - [0x02] = SENSORS_TRIGGER_MODE_ONE_SHOT, - [0x03] = SENSORS_TRIGGER_MODE_SPECIAL - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsTriggerMode)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast<SensorsTriggerMode>(sMode[aIn]); - return NS_OK; -} - -nsresult -Convert(uint32_t aIn, SensorsType& aOut) -{ - static const uint8_t sType[] = { - [0x00] = 0, // invalid, required by gcc - [0x01] = SENSORS_TYPE_ACCELEROMETER, - [0x02] = SENSORS_TYPE_GEOMAGNETIC_FIELD, - [0x03] = SENSORS_TYPE_ORIENTATION, - [0x04] = SENSORS_TYPE_GYROSCOPE, - [0x05] = SENSORS_TYPE_LIGHT, - [0x06] = SENSORS_TYPE_PRESSURE, - [0x07] = SENSORS_TYPE_TEMPERATURE, - [0x08] = SENSORS_TYPE_PROXIMITY, - [0x09] = SENSORS_TYPE_GRAVITY, - [0x0a] = SENSORS_TYPE_LINEAR_ACCELERATION, - [0x0b] = SENSORS_TYPE_ROTATION_VECTOR, - [0x0c] = SENSORS_TYPE_RELATIVE_HUMIDITY, - [0x0d] = SENSORS_TYPE_AMBIENT_TEMPERATURE, - [0x0e] = SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED, - [0x0f] = SENSORS_TYPE_GAME_ROTATION_VECTOR, - [0x10] = SENSORS_TYPE_GYROSCOPE_UNCALIBRATED, - [0x11] = SENSORS_TYPE_SIGNIFICANT_MOTION, - [0x12] = SENSORS_TYPE_STEP_DETECTED, - [0x13] = SENSORS_TYPE_STEP_COUNTER, - [0x14] = SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR, - [0x15] = SENSORS_TYPE_HEART_RATE, - [0x16] = SENSORS_TYPE_TILT_DETECTOR, - [0x17] = SENSORS_TYPE_WAKE_GESTURE, - [0x18] = SENSORS_TYPE_GLANCE_GESTURE, - [0x19] = SENSORS_TYPE_PICK_UP_GESTURE, - [0x1a] = SENSORS_TYPE_WRIST_TILT_GESTURE - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - !aIn, uint32_t, SensorsType) || - MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sType), uint32_t, SensorsType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast<SensorsType>(sType[aIn]); - return NS_OK; -} - -nsresult -Convert(nsresult aIn, SensorsError& aOut) -{ - if (NS_SUCCEEDED(aIn)) { - aOut = SENSORS_ERROR_NONE; - } else if (aIn == NS_ERROR_OUT_OF_MEMORY) { - aOut = SENSORS_ERROR_NOMEM; - } else if (aIn == NS_ERROR_ILLEGAL_VALUE) { - aOut = SENSORS_ERROR_PARM_INVALID; - } else { - aOut = SENSORS_ERROR_FAIL; - } - return NS_OK; -} - -// -// Packing -// -// Pack functions store a value in PDU. See the documentation of the -// HAL IPC framework for more information. -// -// There are currently no sensor-specific pack functions necessary. If -// you add one, put it below. -// - -// -// Unpacking -// -// Unpack function retrieve a value from a PDU. The functions return -// NS_OK on success, or an XPCOM error code otherwise. On sucess, the -// returned value is stored in the second argument |aOut|. -// -// See the documentation of the HAL IPC framework for more information -// on unpack functions. -// - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsDeliveryMode& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsDeliveryMode>(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsError& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsError>(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut); - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsStatus& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion<int32_t, SensorsStatus>(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsTriggerMode& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion<uint8_t, SensorsTriggerMode>(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsType& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion<uint32_t, SensorsType>(aOut)); -} - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsHelpers_h diff --git a/hal/gonk/GonkSensorsInterface.cpp b/hal/gonk/GonkSensorsInterface.cpp deleted file mode 100644 index 51e1ff50c..000000000 --- a/hal/gonk/GonkSensorsInterface.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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 "GonkSensorsInterface.h" -#include "GonkSensorsPollInterface.h" -#include "GonkSensorsRegistryInterface.h" -#include "HalLog.h" -#include <mozilla/ipc/DaemonSocket.h> -#include <mozilla/ipc/DaemonSocketConnector.h> -#include <mozilla/ipc/ListenSocket.h> - -namespace mozilla { -namespace hal { - -using namespace mozilla::ipc; - -// -// GonkSensorsResultHandler -// - -void -GonkSensorsResultHandler::OnError(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast<int>(aError)); -} - -void -GonkSensorsResultHandler::Connect() -{ } - -void -GonkSensorsResultHandler::Disconnect() -{ } - -GonkSensorsResultHandler::~GonkSensorsResultHandler() -{ } - -// -// GonkSensorsNotificationHandler -// - -void -GonkSensorsNotificationHandler::BackendErrorNotification(bool aCrashed) -{ - if (aCrashed) { - HAL_ERR("Sensors backend crashed"); - } else { - HAL_ERR("Error in sensors backend"); - } -} - -GonkSensorsNotificationHandler::~GonkSensorsNotificationHandler() -{ } - -// -// GonkSensorsProtocol -// - -class GonkSensorsProtocol final - : public DaemonSocketIOConsumer - , public GonkSensorsRegistryModule - , public GonkSensorsPollModule -{ -public: - GonkSensorsProtocol(); - - void SetConnection(DaemonSocket* aConnection); - - already_AddRefed<DaemonSocketResultHandler> FetchResultHandler( - const DaemonSocketPDUHeader& aHeader); - - // Methods for |SensorsRegistryModule| and |SensorsPollModule| - // - - nsresult Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) override; - - // Methods for |DaemonSocketIOConsumer| - // - - void Handle(DaemonSocketPDU& aPDU) override; - void StoreResultHandler(const DaemonSocketPDU& aPDU) override; - -private: - void HandleRegistrySvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - void HandlePollSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - - DaemonSocket* mConnection; - nsTArray<RefPtr<DaemonSocketResultHandler>> mResultHandlerQ; -}; - -GonkSensorsProtocol::GonkSensorsProtocol() -{ } - -void -GonkSensorsProtocol::SetConnection(DaemonSocket* aConnection) -{ - mConnection = aConnection; -} - -already_AddRefed<DaemonSocketResultHandler> -GonkSensorsProtocol::FetchResultHandler(const DaemonSocketPDUHeader& aHeader) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - if (aHeader.mOpcode & 0x80) { - return nullptr; // Ignore notifications - } - - RefPtr<DaemonSocketResultHandler> res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - - return res.forget(); -} - -void -GonkSensorsProtocol::HandleRegistrySvc( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - GonkSensorsRegistryModule::HandleSvc(aHeader, aPDU, aRes); -} - -void -GonkSensorsProtocol::HandlePollSvc( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - GonkSensorsPollModule::HandleSvc(aHeader, aPDU, aRes); -} - -// |SensorsRegistryModule|, |SensorsPollModule| - -nsresult -GonkSensorsProtocol::Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) -{ - MOZ_ASSERT(mConnection); - MOZ_ASSERT(aPDU); - - aPDU->SetConsumer(this); - aPDU->SetResultHandler(aRes); - aPDU->UpdateHeader(); - - if (mConnection->GetConnectionStatus() == SOCKET_DISCONNECTED) { - HAL_ERR("Sensors socket is disconnected"); - return NS_ERROR_FAILURE; - } - - mConnection->SendSocketData(aPDU); // Forward PDU to data channel - - return NS_OK; -} - -// |DaemonSocketIOConsumer| - -void -GonkSensorsProtocol::Handle(DaemonSocketPDU& aPDU) -{ - static void (GonkSensorsProtocol::* const HandleSvc[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&, - DaemonSocketResultHandler*) = { - [GonkSensorsRegistryModule::SERVICE_ID] = - &GonkSensorsProtocol::HandleRegistrySvc, - [GonkSensorsPollModule::SERVICE_ID] = - &GonkSensorsProtocol::HandlePollSvc - }; - - DaemonSocketPDUHeader header; - - if (NS_FAILED(UnpackPDU(aPDU, header))) { - return; - } - if (!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc)) || - !HandleSvc[header.mService]) { - HAL_ERR("Sensors service %d unknown", header.mService); - return; - } - - RefPtr<DaemonSocketResultHandler> res = FetchResultHandler(header); - - (this->*(HandleSvc[header.mService]))(header, aPDU, res); -} - -void -GonkSensorsProtocol::StoreResultHandler(const DaemonSocketPDU& aPDU) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - mResultHandlerQ.AppendElement(aPDU.GetResultHandler()); -} - -// -// GonkSensorsInterface -// - -GonkSensorsInterface* -GonkSensorsInterface::GetInstance() -{ - static GonkSensorsInterface* sGonkSensorsInterface; - - if (sGonkSensorsInterface) { - return sGonkSensorsInterface; - } - - sGonkSensorsInterface = new GonkSensorsInterface(); - - return sGonkSensorsInterface; -} - -void -GonkSensorsInterface::SetNotificationHandler( - GonkSensorsNotificationHandler* aNotificationHandler) -{ - MOZ_ASSERT(NS_IsMainThread()); - - mNotificationHandler = aNotificationHandler; -} - -/* - * The connect procedure consists of several steps. - * - * (1) Start listening for the command channel's socket connection: We - * do this before anything else, so that we don't miss connection - * requests from the Sensors daemon. This step will create a listen - * socket. - * - * (2) Start the Sensors daemon: When the daemon starts up it will open - * a socket connection to Gecko and thus create the data channel. - * Gecko already opened the listen socket in step (1). Step (2) ends - * with the creation of the data channel. - * - * (3) Signal success to the caller. - * - * If any step fails, we roll-back the procedure and signal an error to the - * caller. - */ -void -GonkSensorsInterface::Connect(GonkSensorsNotificationHandler* aNotificationHandler, - GonkSensorsResultHandler* aRes) -{ -#define BASE_SOCKET_NAME "sensorsd" - static unsigned long POSTFIX_LENGTH = 16; - - // If we could not cleanup properly before and an old - // instance of the daemon is still running, we kill it - // here. - mozilla::hal::StopSystemService("sensorsd"); - - mNotificationHandler = aNotificationHandler; - - mResultHandlerQ.AppendElement(aRes); - - if (!mProtocol) { - mProtocol = MakeUnique<GonkSensorsProtocol>(); - } - - if (!mListenSocket) { - mListenSocket = new ListenSocket(this, LISTEN_SOCKET); - } - - // Init, step 1: Listen for data channel... */ - - if (!mDataSocket) { - mDataSocket = new DaemonSocket(mProtocol.get(), this, DATA_SOCKET); - } else if (mDataSocket->GetConnectionStatus() == SOCKET_CONNECTED) { - // Command channel should not be open; let's close it. - mDataSocket->Close(); - } - - // The listen socket's name is generated with a random postfix. This - // avoids naming collisions if we still have a listen socket from a - // previously failed cleanup. It also makes it hard for malicious - // external programs to capture the socket name or connect before - // the daemon can do so. If no random postfix can be generated, we - // simply use the base name as-is. - nsresult rv = DaemonSocketConnector::CreateRandomAddressString( - NS_LITERAL_CSTRING(BASE_SOCKET_NAME), POSTFIX_LENGTH, mListenSocketName); - if (NS_FAILED(rv)) { - mListenSocketName.AssignLiteral(BASE_SOCKET_NAME); - } - - rv = mListenSocket->Listen(new DaemonSocketConnector(mListenSocketName), - mDataSocket); - if (NS_FAILED(rv)) { - OnConnectError(DATA_SOCKET); - return; - } - - // The protocol implementation needs a data channel for - // sending commands to the daemon. We set it here, because - // this is the earliest time when it's available. - mProtocol->SetConnection(mDataSocket); -} - -/* - * Disconnecting is inverse to connecting. - * - * (1) Close data socket: We close the data channel and the daemon will - * will notice. Once we see the socket's disconnect, we continue with - * the cleanup. - * - * (2) Close listen socket: The listen socket is not active any longer - * and we simply close it. - * - * (3) Signal success to the caller. - * - * We don't have to stop the daemon explicitly. It will cleanup and quit - * after it noticed the closing of the data channel - * - * Rolling back half-completed cleanups is not possible. In the case of - * an error, we simply push forward and try to recover during the next - * initialization. - */ -void -GonkSensorsInterface::Disconnect(GonkSensorsResultHandler* aRes) -{ - mNotificationHandler = nullptr; - - // Cleanup, step 1: Close data channel - mDataSocket->Close(); - - mResultHandlerQ.AppendElement(aRes); -} - -GonkSensorsRegistryInterface* -GonkSensorsInterface::GetSensorsRegistryInterface() -{ - if (mRegistryInterface) { - return mRegistryInterface.get(); - } - - mRegistryInterface = MakeUnique<GonkSensorsRegistryInterface>(mProtocol.get()); - - return mRegistryInterface.get(); -} - -GonkSensorsPollInterface* -GonkSensorsInterface::GetSensorsPollInterface() -{ - if (mPollInterface) { - return mPollInterface.get(); - } - - mPollInterface = MakeUnique<GonkSensorsPollInterface>(mProtocol.get()); - - return mPollInterface.get(); -} - -GonkSensorsInterface::GonkSensorsInterface() - : mNotificationHandler(nullptr) -{ } - -GonkSensorsInterface::~GonkSensorsInterface() -{ } - -void -GonkSensorsInterface::DispatchError(GonkSensorsResultHandler* aRes, - SensorsError aError) -{ - DaemonResultRunnable1<GonkSensorsResultHandler, void, - SensorsError, SensorsError>::Dispatch( - aRes, &GonkSensorsResultHandler::OnError, - ConstantInitOp1<SensorsError>(aError)); -} - -void -GonkSensorsInterface::DispatchError( - GonkSensorsResultHandler* aRes, nsresult aRv) -{ - SensorsError error; - - if (NS_FAILED(Convert(aRv, error))) { - error = SENSORS_ERROR_FAIL; - } - DispatchError(aRes, error); -} - -// |DaemonSocketConsumer|, |ListenSocketConsumer| - -void -GonkSensorsInterface::OnConnectSuccess(int aIndex) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); - - switch (aIndex) { - case LISTEN_SOCKET: { - // Init, step 2: Start Sensors daemon - nsCString args("-a "); - args.Append(mListenSocketName); - mozilla::hal::StartSystemService("sensorsd", args.get()); - } - break; - case DATA_SOCKET: - if (!mResultHandlerQ.IsEmpty()) { - // Init, step 3: Signal success - RefPtr<GonkSensorsResultHandler> res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - if (res) { - res->Connect(); - } - } - break; - } -} - -void -GonkSensorsInterface::OnConnectError(int aIndex) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); - - switch (aIndex) { - case DATA_SOCKET: - // Stop daemon and close listen socket - mozilla::hal::StopSystemService("sensorsd"); - mListenSocket->Close(); - // fall through - case LISTEN_SOCKET: - if (!mResultHandlerQ.IsEmpty()) { - // Signal error to caller - RefPtr<GonkSensorsResultHandler> res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - if (res) { - DispatchError(res, SENSORS_ERROR_FAIL); - } - } - break; - } -} - -/* - * Disconnects can happend - * - * (a) during startup, - * (b) during regular service, or - * (c) during shutdown. - * - * For cases (a) and (c), |mResultHandlerQ| contains an element. For - * case (b) |mResultHandlerQ| will be empty. This distinguishes a crash in - * the daemon. The following procedure to recover from crashes consists of - * several steps for case (b). - * - * (1) Close listen socket. - * (2) Wait for all sockets to be disconnected and inform caller about - * the crash. - * (3) After all resources have been cleaned up, let the caller restart - * the daemon. - */ -void -GonkSensorsInterface::OnDisconnect(int aIndex) -{ - MOZ_ASSERT(NS_IsMainThread()); - - switch (aIndex) { - case DATA_SOCKET: - // Cleanup, step 2 (Recovery, step 1): Close listen socket - mListenSocket->Close(); - break; - case LISTEN_SOCKET: - // Cleanup, step 3: Signal success to caller - if (!mResultHandlerQ.IsEmpty()) { - RefPtr<GonkSensorsResultHandler> res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - if (res) { - res->Disconnect(); - } - } - break; - } - - /* For recovery make sure all sockets disconnected, in order to avoid - * the remaining disconnects interfere with the restart procedure. - */ - if (mNotificationHandler && mResultHandlerQ.IsEmpty()) { - if (mListenSocket->GetConnectionStatus() == SOCKET_DISCONNECTED && - mDataSocket->GetConnectionStatus() == SOCKET_DISCONNECTED) { - // Recovery, step 2: Notify the caller to prepare the restart procedure. - mNotificationHandler->BackendErrorNotification(true); - mNotificationHandler = nullptr; - } - } -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsInterface.h b/hal/gonk/GonkSensorsInterface.h deleted file mode 100644 index 6e356dc36..000000000 --- a/hal/gonk/GonkSensorsInterface.h +++ /dev/null @@ -1,191 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -/* - * The sensors interface gives you access to the low-level sensors code - * in a platform-independent manner. The interfaces in this file allow - * for starting an stopping the sensors driver. Specific functionality - * is implemented in sub-interfaces. - */ - -#ifndef hal_gonk_GonkSensorsInterface_h -#define hal_gonk_GonkSensorsInterface_h - -#include <mozilla/ipc/DaemonSocketConsumer.h> -#include <mozilla/ipc/DaemonSocketMessageHandlers.h> -#include <mozilla/ipc/ListenSocketConsumer.h> -#include <mozilla/UniquePtr.h> -#include "SensorsTypes.h" - -namespace mozilla { -namespace ipc { - -class DaemonSocket; -class ListenSocket; - -} -} - -namespace mozilla { -namespace hal { - -class GonkSensorsPollInterface; -class GonkSensorsProtocol; -class GonkSensorsRegistryInterface; - -/** - * This class is the result-handler interface for the Sensors - * interface. Methods always run on the main thread. - */ -class GonkSensorsResultHandler - : public mozilla::ipc::DaemonSocketResultHandler -{ -public: - - /** - * Called if a command failed. - * - * @param aError The error code. - */ - virtual void OnError(SensorsError aError); - - /** - * The callback method for |GonkSensorsInterface::Connect|. - */ - virtual void Connect(); - - /** - * The callback method for |GonkSensorsInterface::Connect|. - */ - virtual void Disconnect(); - -protected: - virtual ~GonkSensorsResultHandler(); -}; - -/** - * This is the notification-handler interface. Implement this classes - * methods to handle event and notifications from the sensors daemon. - * All methods run on the main thread. - */ -class GonkSensorsNotificationHandler -{ -public: - - /** - * This notification is called when the backend code fails - * unexpectedly. Save state in the high-level code and restart - * the driver. - * - * @param aCrash True is the sensors driver crashed. - */ - virtual void BackendErrorNotification(bool aCrashed); - -protected: - virtual ~GonkSensorsNotificationHandler(); -}; - -/** - * This class implements the public interface to the Sensors functionality - * and driver. Use |GonkSensorsInterface::GetInstance| to retrieve an instance. - * All methods run on the main thread. - */ -class GonkSensorsInterface final - : public mozilla::ipc::DaemonSocketConsumer - , public mozilla::ipc::ListenSocketConsumer -{ -public: - /** - * Returns an instance of the Sensors backend. This code can return - * |nullptr| if no Sensors backend is available. - * - * @return An instance of |GonkSensorsInterface|. - */ - static GonkSensorsInterface* GetInstance(); - - /** - * This method sets the notification handler for sensor notifications. Call - * this method immediately after retreiving an instance of the class, or you - * won't be able able to receive notifications. You may not free the handler - * class while the Sensors backend is connected. - * - * @param aNotificationHandler An instance of a notification handler. - */ - void SetNotificationHandler( - GonkSensorsNotificationHandler* aNotificationHandler); - - /** - * This method starts the Sensors backend and establishes ad connection - * with Gecko. This is a multi-step process and errors are signalled by - * |GonkSensorsNotificationHandler::BackendErrorNotification|. If you see - * this notification before the connection has been established, it's - * certainly best to assume the Sensors backend to be not evailable. - * - * @param aRes The result handler. - */ - void Connect(GonkSensorsNotificationHandler* aNotificationHandler, - GonkSensorsResultHandler* aRes); - - /** - * This method disconnects Gecko from the Sensors backend and frees - * the backend's resources. This will invalidate all interfaces and - * state. Don't use any sensors functionality without reconnecting - * first. - * - * @param aRes The result handler. - */ - void Disconnect(GonkSensorsResultHandler* aRes); - - /** - * Returns the Registry interface for the connected Sensors backend. - * - * @return An instance of the Sensors Registry interface. - */ - GonkSensorsRegistryInterface* GetSensorsRegistryInterface(); - - /** - * Returns the Poll interface for the connected Sensors backend. - * - * @return An instance of the Sensors Poll interface. - */ - GonkSensorsPollInterface* GetSensorsPollInterface(); - -private: - enum Channel { - LISTEN_SOCKET, - DATA_SOCKET - }; - - GonkSensorsInterface(); - ~GonkSensorsInterface(); - - void DispatchError(GonkSensorsResultHandler* aRes, SensorsError aError); - void DispatchError(GonkSensorsResultHandler* aRes, nsresult aRv); - - // Methods for |DaemonSocketConsumer| and |ListenSocketConsumer| - // - - void OnConnectSuccess(int aIndex) override; - void OnConnectError(int aIndex) override; - void OnDisconnect(int aIndex) override; - - nsCString mListenSocketName; - RefPtr<mozilla::ipc::ListenSocket> mListenSocket; - RefPtr<mozilla::ipc::DaemonSocket> mDataSocket; - UniquePtr<GonkSensorsProtocol> mProtocol; - - nsTArray<RefPtr<GonkSensorsResultHandler> > mResultHandlerQ; - - GonkSensorsNotificationHandler* mNotificationHandler; - - UniquePtr<GonkSensorsRegistryInterface> mRegistryInterface; - UniquePtr<GonkSensorsPollInterface> mPollInterface; -}; - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsInterface_h diff --git a/hal/gonk/GonkSensorsPollInterface.cpp b/hal/gonk/GonkSensorsPollInterface.cpp deleted file mode 100644 index d4edc2e7a..000000000 --- a/hal/gonk/GonkSensorsPollInterface.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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 "GonkSensorsPollInterface.h" -#include "HalLog.h" -#include <mozilla/UniquePtr.h> - -namespace mozilla { -namespace hal { - -using namespace mozilla::ipc; - -// -// GonkSensorsPollResultHandler -// - -void -GonkSensorsPollResultHandler::OnError(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast<int>(aError)); -} - -void -GonkSensorsPollResultHandler::EnableSensor() -{ } - -void -GonkSensorsPollResultHandler::DisableSensor() -{ } - -void -GonkSensorsPollResultHandler::SetPeriod() -{ } - -GonkSensorsPollResultHandler::~GonkSensorsPollResultHandler() -{ } - -// -// GonkSensorsPollNotificationHandler -// - -void -GonkSensorsPollNotificationHandler::ErrorNotification(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast<int>(aError)); -} - -void -GonkSensorsPollNotificationHandler::SensorDetectedNotification( - int32_t aId, - SensorsType aType, - float aRange, - float aResolution, - float aPower, - int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode) -{ } - -void -GonkSensorsPollNotificationHandler::SensorLostNotification(int32_t aId) -{ } - -void -GonkSensorsPollNotificationHandler::EventNotification(int32_t aId, - const SensorsEvent& aEvent) -{ } - -GonkSensorsPollNotificationHandler::~GonkSensorsPollNotificationHandler() -{ } - -// -// GonkSensorsPollModule -// - -GonkSensorsPollModule::GonkSensorsPollModule() - : mProtocolVersion(0) -{ } - -GonkSensorsPollModule::~GonkSensorsPollModule() -{ } - -nsresult -GonkSensorsPollModule::SetProtocolVersion(unsigned long aProtocolVersion) -{ - if ((aProtocolVersion < MIN_PROTOCOL_VERSION) || - (aProtocolVersion > MAX_PROTOCOL_VERSION)) { - HAL_ERR("Sensors Poll protocol version %lu not supported", - aProtocolVersion); - return NS_ERROR_ILLEGAL_VALUE; - } - mProtocolVersion = aProtocolVersion; - return NS_OK; -} - -void -GonkSensorsPollModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsPollModule::* const HandleOp[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&, - DaemonSocketResultHandler*) = { - [0] = &GonkSensorsPollModule::HandleRsp, - [1] = &GonkSensorsPollModule::HandleNtf - }; - - MOZ_ASSERT(!NS_IsMainThread()); // I/O thread - - // Negate twice to map bit to 0/1 - unsigned long isNtf = !!(aHeader.mOpcode & 0x80); - - (this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes); -} - -// Commands -// - -nsresult -GonkSensorsPollModule::EnableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - UniquePtr<DaemonSocketPDU> pdu = - MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_ENABLE_SENSOR, 0); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu.get(), aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.release(); - return NS_OK; -} - -nsresult -GonkSensorsPollModule::DisableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - UniquePtr<DaemonSocketPDU> pdu = - MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISABLE_SENSOR, 0); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu.get(), aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.release(); - return NS_OK; -} - -nsresult -GonkSensorsPollModule::SetPeriodCmd(int32_t aId, uint64_t aPeriod, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - UniquePtr<DaemonSocketPDU> pdu = - MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_PERIOD, 0); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = PackPDU(aPeriod, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu.get(), aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.release(); - return NS_OK; -} - -// Responses -// - -void -GonkSensorsPollModule::ErrorRsp( - const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes) -{ - ErrorRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::OnError, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::EnableSensorRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::EnableSensor, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::DisableSensorRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::DisableSensor, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::SetPeriodRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::SetPeriod, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::HandleRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsPollModule::* const sHandleRsp[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&, - GonkSensorsPollResultHandler*) = { - [OPCODE_ERROR] = &GonkSensorsPollModule::ErrorRsp, - [OPCODE_ENABLE_SENSOR] = &GonkSensorsPollModule::EnableSensorRsp, - [OPCODE_DISABLE_SENSOR] = &GonkSensorsPollModule::DisableSensorRsp, - [OPCODE_SET_PERIOD] = &GonkSensorsPollModule::SetPeriodRsp, - }; - - MOZ_ASSERT(!NS_IsMainThread()); // I/O thread - - if (!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(sHandleRsp)) || - !sHandleRsp[aHeader.mOpcode]) { - HAL_ERR("Sensors poll response opcode %d unknown", aHeader.mOpcode); - return; - } - - RefPtr<GonkSensorsPollResultHandler> res = - static_cast<GonkSensorsPollResultHandler*>(aRes); - - if (!res) { - return; // Return early if no result handler has been set for response - } - - (this->*(sHandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); -} - -// Notifications -// - -// Returns the current notification handler to a notification runnable -class GonkSensorsPollModule::NotificationHandlerWrapper final -{ -public: - typedef GonkSensorsPollNotificationHandler ObjectType; - - static ObjectType* GetInstance() - { - MOZ_ASSERT(NS_IsMainThread()); - - return sNotificationHandler; - } - - static GonkSensorsPollNotificationHandler* sNotificationHandler; -}; - -GonkSensorsPollNotificationHandler* - GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler; - -void -GonkSensorsPollModule::ErrorNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - ErrorNotification::Dispatch( - &GonkSensorsPollNotificationHandler::ErrorNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::SensorDetectedNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - SensorDetectedNotification::Dispatch( - &GonkSensorsPollNotificationHandler::SensorDetectedNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::SensorLostNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - SensorLostNotification::Dispatch( - &GonkSensorsPollNotificationHandler::SensorLostNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::EventNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - EventNotification::Dispatch( - &GonkSensorsPollNotificationHandler::EventNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::HandleNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsPollModule::* const sHandleNtf[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { - [0] = &GonkSensorsPollModule::ErrorNtf, - [1] = &GonkSensorsPollModule::SensorDetectedNtf, - [2] = &GonkSensorsPollModule::SensorLostNtf, - [3] = &GonkSensorsPollModule::EventNtf - }; - - MOZ_ASSERT(!NS_IsMainThread()); - - uint8_t index = aHeader.mOpcode - 0x80; - - if (!(index < MOZ_ARRAY_LENGTH(sHandleNtf)) || !sHandleNtf[index]) { - HAL_ERR("Sensors poll notification opcode %d unknown", aHeader.mOpcode); - return; - } - - (this->*(sHandleNtf[index]))(aHeader, aPDU); -} - -// -// GonkSensorsPollInterface -// - -GonkSensorsPollInterface::GonkSensorsPollInterface( - GonkSensorsPollModule* aModule) - : mModule(aModule) -{ } - -GonkSensorsPollInterface::~GonkSensorsPollInterface() -{ } - -void -GonkSensorsPollInterface::SetNotificationHandler( - GonkSensorsPollNotificationHandler* aNotificationHandler) -{ - MOZ_ASSERT(NS_IsMainThread()); - - GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler = - aNotificationHandler; -} - -nsresult -GonkSensorsPollInterface::SetProtocolVersion(unsigned long aProtocolVersion) -{ - MOZ_ASSERT(mModule); - - return mModule->SetProtocolVersion(aProtocolVersion); -} - -void -GonkSensorsPollInterface::EnableSensor(int32_t aId, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->EnableSensorCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsPollInterface::DisableSensor(int32_t aId, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->DisableSensorCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsPollInterface::SetPeriod(int32_t aId, uint64_t aPeriod, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->SetPeriodCmd(aId, aPeriod, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsPollInterface::DispatchError( - GonkSensorsPollResultHandler* aRes, SensorsError aError) -{ - DaemonResultRunnable1<GonkSensorsPollResultHandler, void, - SensorsError, SensorsError>::Dispatch( - aRes, &GonkSensorsPollResultHandler::OnError, - ConstantInitOp1<SensorsError>(aError)); -} - -void -GonkSensorsPollInterface::DispatchError( - GonkSensorsPollResultHandler* aRes, nsresult aRv) -{ - SensorsError error; - - if (NS_FAILED(Convert(aRv, error))) { - error = SENSORS_ERROR_FAIL; - } - DispatchError(aRes, error); -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsPollInterface.h b/hal/gonk/GonkSensorsPollInterface.h deleted file mode 100644 index 89381a9bd..000000000 --- a/hal/gonk/GonkSensorsPollInterface.h +++ /dev/null @@ -1,340 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -/* - * The poll interface gives yo access to the Sensors daemon's Poll service, - * which handles sensors. The poll service will inform you when sensors are - * detected or removed from the system. You can activate (or deactivate) - * existing sensors and poll will deliver the sensors' events. - * - * All public methods and callback methods run on the main thread. - */ - -#ifndef hal_gonk_GonkSensorsPollInterface_h -#define hal_gonk_GonkSensorsPollInterface_h - -#include <mozilla/ipc/DaemonRunnables.h> -#include <mozilla/ipc/DaemonSocketMessageHandlers.h> -#include "SensorsTypes.h" - -namespace mozilla { -namespace ipc { - -class DaemonSocketPDU; -class DaemonSocketPDUHeader; - -} -} - -namespace mozilla { -namespace hal { - -class SensorsInterface; - -using mozilla::ipc::DaemonSocketPDU; -using mozilla::ipc::DaemonSocketPDUHeader; -using mozilla::ipc::DaemonSocketResultHandler; - -/** - * This class is the result-handler interface for the Sensors - * Poll interface. Methods always run on the main thread. - */ -class GonkSensorsPollResultHandler : public DaemonSocketResultHandler -{ -public: - - /** - * Called if a poll command failed. - * - * @param aError The error code. - */ - virtual void OnError(SensorsError aError); - - /** - * The callback method for |GonkSensorsPollInterface::EnableSensor|. - */ - virtual void EnableSensor(); - - /** - * The callback method for |GonkSensorsPollInterface::DisableSensor|. - */ - virtual void DisableSensor(); - - /** - * The callback method for |GonkSensorsPollInterface::SetPeriod|. - */ - virtual void SetPeriod(); - -protected: - virtual ~GonkSensorsPollResultHandler(); -}; - -/** - * This is the notification-handler interface. Implement this classes - * methods to handle event and notifications from the sensors daemon. - */ -class GonkSensorsPollNotificationHandler -{ -public: - - /** - * The notification handler for errors. You'll receive this call if - * there's been a critical error in the daemon. Either try to handle - * the error, or restart the daemon. - * - * @param aError The error code. - */ - virtual void ErrorNotification(SensorsError aError); - - /** - * This methods gets call when a new sensor has been detected. - * - * @param aId The sensor's id. - * @param aType The sensor's type. - * @param aRange The sensor's maximum value. - * @param aResolution The minimum difference between two consecutive values. - * @param aPower The sensor's power consumption (in mA). - * @param aMinPeriod The minimum time between two events (in ns). - * @param aMaxPeriod The maximum time between two events (in ns). - * @param aTriggerMode The sensor's mode for triggering events. - * @param aDeliveryMode The sensor's urgency for event delivery. - */ - virtual void SensorDetectedNotification(int32_t aId, SensorsType aType, - float aRange, float aResolution, - float aPower, int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode); - - /** - * This methods gets call when an existing sensor has been removed. - * - * @param aId The sensor's id. - */ - virtual void SensorLostNotification(int32_t aId); - - /** - * This is the callback methods for sensor events. Only activated sensors - * generate events. All sensors are disabled by default. The actual data - * of the event depends on the sensor type. - * - * @param aId The sensor's id. - * @param aEvent The event's data. - */ - virtual void EventNotification(int32_t aId, const SensorsEvent& aEvent); - -protected: - virtual ~GonkSensorsPollNotificationHandler(); -}; - -/** - * This is the module class for the Sensors poll component. It handles PDU - * packing and unpacking. Methods are either executed on the main thread or - * the I/O thread. - * - * This is an internal class, use |GonkSensorsPollInterface| instead. - */ -class GonkSensorsPollModule -{ -public: - class NotificationHandlerWrapper; - - enum { - SERVICE_ID = 0x01 - }; - - enum { - OPCODE_ERROR = 0x00, - OPCODE_ENABLE_SENSOR = 0x01, - OPCODE_DISABLE_SENSOR = 0x02, - OPCODE_SET_PERIOD = 0x03 - }; - - enum { - MIN_PROTOCOL_VERSION = 1, - MAX_PROTOCOL_VERSION = 1 - }; - - virtual nsresult Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) = 0; - - nsresult SetProtocolVersion(unsigned long aProtocolVersion); - - // - // Commands - // - - nsresult EnableSensorCmd(int32_t aId, - GonkSensorsPollResultHandler* aRes); - - nsresult DisableSensorCmd(int32_t aId, - GonkSensorsPollResultHandler* aRes); - - nsresult SetPeriodCmd(int32_t aId, uint64_t aPeriod, - GonkSensorsPollResultHandler* aRes); - -protected: - GonkSensorsPollModule(); - virtual ~GonkSensorsPollModule(); - - void HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - -private: - - // - // Responses - // - - typedef mozilla::ipc::DaemonResultRunnable0< - GonkSensorsPollResultHandler, void> - ResultRunnable; - - typedef mozilla::ipc::DaemonResultRunnable1< - GonkSensorsPollResultHandler, void, SensorsError, SensorsError> - ErrorRunnable; - - void ErrorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void EnableSensorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void DisableSensorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void SetPeriodRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void HandleRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - - // - // Notifications - // - - typedef mozilla::ipc::DaemonNotificationRunnable1< - NotificationHandlerWrapper, void, SensorsError> - ErrorNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable9< - NotificationHandlerWrapper, void, int32_t, SensorsType, - float, float, float, int32_t, int32_t, SensorsTriggerMode, - SensorsDeliveryMode> - SensorDetectedNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable1< - NotificationHandlerWrapper, void, int32_t> - SensorLostNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable2< - NotificationHandlerWrapper, void, int32_t, SensorsEvent, int32_t, - const SensorsEvent&> - EventNotification; - - class SensorDetectedInitOp; - class SensorLostInitOp; - class EventInitOp; - - void ErrorNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void SensorDetectedNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void SensorLostNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void EventNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void HandleNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - -private: - unsigned long mProtocolVersion; -}; - -/** - * This class implements the public interface to the Sensors poll - * component. Use |SensorsInterface::GetPollInterface| to retrieve - * an instance. All methods run on the main thread. - */ -class GonkSensorsPollInterface final -{ -public: - GonkSensorsPollInterface(GonkSensorsPollModule* aModule); - ~GonkSensorsPollInterface(); - - /** - * This method sets the notification handler for poll notifications. Call - * this method immediately after registering the module. Otherwise you won't - * be able able to receive poll notifications. You may not free the handler - * class while the poll component is regsitered. - * - * @param aNotificationHandler An instance of a poll notification handler. - */ - void SetNotificationHandler( - GonkSensorsPollNotificationHandler* aNotificationHandler); - - /** - * This method sets the protocol version. You should set it to the - * value that has been returned from the backend when registering the - * Poll service. You cannot send or receive messages before setting - * the protocol version. - * - * @param aProtocolVersion - * @return NS_OK for supported versions, or an XPCOM error code otherwise. - */ - nsresult SetProtocolVersion(unsigned long aProtocolVersion); - - /** - * Enables an existing sensor. The sensor id will have been delivered in - * a SensorDetectedNotification. - * - * @param aId The sensor's id. - * @param aRes The result handler. - */ - void EnableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes); - - /** - * Disables an existing sensor. The sensor id will have been delivered in - * a SensorDetectedNotification. - * - * @param aId The sensor's id. - * @param aRes The result handler. - */ - void DisableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes); - - /** - * Sets the period for a sensor. The sensor id will have been delivered in - * a SensorDetectedNotification. The value for the period should be between - * the sensor's minimum and maximum period. - * - * @param aId The sensor's id. - * @param aPeriod The sensor's new period. - * @param aRes The result handler. - */ - void SetPeriod(int32_t aId, uint64_t aPeriod, GonkSensorsPollResultHandler* aRes); - -private: - void DispatchError(GonkSensorsPollResultHandler* aRes, SensorsError aError); - void DispatchError(GonkSensorsPollResultHandler* aRes, nsresult aRv); - - GonkSensorsPollModule* mModule; -}; - -} // hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsPollInterface_h diff --git a/hal/gonk/GonkSensorsRegistryInterface.cpp b/hal/gonk/GonkSensorsRegistryInterface.cpp deleted file mode 100644 index 601dc7a2a..000000000 --- a/hal/gonk/GonkSensorsRegistryInterface.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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 "GonkSensorsRegistryInterface.h" -#include "GonkSensorsHelpers.h" -#include "HalLog.h" -#include <mozilla/UniquePtr.h> - -namespace mozilla { -namespace hal { - -using namespace mozilla::ipc; - -// -// GonkSensorsRegistryResultHandler -// - -void -GonkSensorsRegistryResultHandler::OnError(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast<int>(aError)); -} - -void -GonkSensorsRegistryResultHandler::RegisterModule(uint32_t aProtocolVersion) -{ } - -void -GonkSensorsRegistryResultHandler::UnregisterModule() -{ } - -GonkSensorsRegistryResultHandler::~GonkSensorsRegistryResultHandler() -{ } - -// -// GonkSensorsRegistryModule -// - -GonkSensorsRegistryModule::~GonkSensorsRegistryModule() -{ } - -void -GonkSensorsRegistryModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsRegistryModule::* const HandleRsp[])( - const DaemonSocketPDUHeader&, - DaemonSocketPDU&, - GonkSensorsRegistryResultHandler*) = { - [OPCODE_ERROR] = &GonkSensorsRegistryModule::ErrorRsp, - [OPCODE_REGISTER_MODULE] = &GonkSensorsRegistryModule::RegisterModuleRsp, - [OPCODE_UNREGISTER_MODULE] = &GonkSensorsRegistryModule::UnregisterModuleRsp - }; - - if ((aHeader.mOpcode >= MOZ_ARRAY_LENGTH(HandleRsp)) || - !HandleRsp[aHeader.mOpcode]) { - HAL_ERR("Sensors registry response opcode %d unknown", aHeader.mOpcode); - return; - } - - RefPtr<GonkSensorsRegistryResultHandler> res = - static_cast<GonkSensorsRegistryResultHandler*>(aRes); - - if (!res) { - return; // Return early if no result handler has been set - } - - (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); -} - -// Commands -// - -nsresult -GonkSensorsRegistryModule::RegisterModuleCmd( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - UniquePtr<DaemonSocketPDU> pdu = - MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_REGISTER_MODULE, 0); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu.get(), aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.release(); - return NS_OK; -} - -nsresult -GonkSensorsRegistryModule::UnregisterModuleCmd( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - UniquePtr<DaemonSocketPDU> pdu = - MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_UNREGISTER_MODULE, 0); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu.get(), aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.release(); - return NS_OK; -} - -// Responses -// - -void -GonkSensorsRegistryModule::ErrorRsp( - const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, GonkSensorsRegistryResultHandler* aRes) -{ - ErrorRunnable::Dispatch( - aRes, &GonkSensorsRegistryResultHandler::OnError, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsRegistryModule::RegisterModuleRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes) -{ - Uint32ResultRunnable::Dispatch( - aRes, - &GonkSensorsRegistryResultHandler::RegisterModule, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsRegistryModule::UnregisterModuleRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, - &GonkSensorsRegistryResultHandler::UnregisterModule, - UnpackPDUInitOp(aPDU)); -} - -// -// GonkSensorsRegistryInterface -// - -GonkSensorsRegistryInterface::GonkSensorsRegistryInterface( - GonkSensorsRegistryModule* aModule) - : mModule(aModule) -{ } - -GonkSensorsRegistryInterface::~GonkSensorsRegistryInterface() -{ } - -void -GonkSensorsRegistryInterface::RegisterModule( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->RegisterModuleCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsRegistryInterface::UnregisterModule( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->UnregisterModuleCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsRegistryInterface::DispatchError( - GonkSensorsRegistryResultHandler* aRes, SensorsError aError) -{ - DaemonResultRunnable1<GonkSensorsRegistryResultHandler, void, - SensorsError, SensorsError>::Dispatch( - aRes, &GonkSensorsRegistryResultHandler::OnError, - ConstantInitOp1<SensorsError>(aError)); -} - -void -GonkSensorsRegistryInterface::DispatchError( - GonkSensorsRegistryResultHandler* aRes, nsresult aRv) -{ - SensorsError error; - - if (NS_FAILED(Convert(aRv, error))) { - error = SENSORS_ERROR_FAIL; - } - DispatchError(aRes, error); -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsRegistryInterface.h b/hal/gonk/GonkSensorsRegistryInterface.h deleted file mode 100644 index a9d98d653..000000000 --- a/hal/gonk/GonkSensorsRegistryInterface.h +++ /dev/null @@ -1,182 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -/* - * The registry interface gives yo access to the Sensors daemon's Registry - * service. The purpose of the service is to register and setup all other - * services, and make them available. - * - * All public methods and callback methods run on the main thread. - */ - -#ifndef hal_gonk_GonkSensorsRegistryInterface_h -#define hal_gonk_GonkSensorsRegistryInterface_h - -#include <mozilla/ipc/DaemonRunnables.h> -#include <mozilla/ipc/DaemonSocketMessageHandlers.h> -#include "SensorsTypes.h" - -namespace mozilla { -namespace ipc { - -class DaemonSocketPDU; -class DaemonSocketPDUHeader; - -} -} - -namespace mozilla { -namespace hal { - -class SensorsInterface; - -using mozilla::ipc::DaemonSocketPDU; -using mozilla::ipc::DaemonSocketPDUHeader; -using mozilla::ipc::DaemonSocketResultHandler; - -/** - * This class is the result-handler interface for the Sensors - * Registry interface. Methods always run on the main thread. - */ -class GonkSensorsRegistryResultHandler : public DaemonSocketResultHandler -{ -public: - - /** - * Called if a registry command failed. - * - * @param aError The error code. - */ - virtual void OnError(SensorsError aError); - - /** - * The callback method for |GonkSensorsRegistryInterface::RegisterModule|. - * - * @param aProtocolVersion The daemon's protocol version. Make sure it's - * compatible with Gecko's implementation. - */ - virtual void RegisterModule(uint32_t aProtocolVersion); - - /** - * The callback method for |SensorsRegsitryInterface::UnregisterModule|. - */ - virtual void UnregisterModule(); - -protected: - virtual ~GonkSensorsRegistryResultHandler(); -}; - -/** - * This is the module class for the Sensors registry component. It handles - * PDU packing and unpacking. Methods are either executed on the main thread - * or the I/O thread. - * - * This is an internal class, use |GonkSensorsRegistryInterface| instead. - */ -class GonkSensorsRegistryModule -{ -public: - enum { - SERVICE_ID = 0x00 - }; - - enum { - OPCODE_ERROR = 0x00, - OPCODE_REGISTER_MODULE = 0x01, - OPCODE_UNREGISTER_MODULE = 0x02 - }; - - virtual nsresult Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) = 0; - - // - // Commands - // - - nsresult RegisterModuleCmd(uint8_t aId, - GonkSensorsRegistryResultHandler* aRes); - - nsresult UnregisterModuleCmd(uint8_t aId, - GonkSensorsRegistryResultHandler* aRes); - -protected: - virtual ~GonkSensorsRegistryModule(); - - void HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes); - - // - // Responses - // - - typedef mozilla::ipc::DaemonResultRunnable0< - GonkSensorsRegistryResultHandler, void> - ResultRunnable; - - typedef mozilla::ipc::DaemonResultRunnable1< - GonkSensorsRegistryResultHandler, void, uint32_t, uint32_t> - Uint32ResultRunnable; - - typedef mozilla::ipc::DaemonResultRunnable1< - GonkSensorsRegistryResultHandler, void, SensorsError, SensorsError> - ErrorRunnable; - - void ErrorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes); - - void RegisterModuleRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes); - - void UnregisterModuleRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes); -}; - -/** - * This class implements the public interface to the Sensors Registry - * component. Use |SensorsInterface::GetRegistryInterface| to retrieve - * an instance. All methods run on the main thread. - */ -class GonkSensorsRegistryInterface final -{ -public: - GonkSensorsRegistryInterface(GonkSensorsRegistryModule* aModule); - ~GonkSensorsRegistryInterface(); - - /** - * Sends a RegisterModule command to the Sensors daemon. When the - * result handler's |RegisterModule| method gets called, the service - * has been registered successfully and can be used. - * - * @param aId The id of the service that is to be registered. - * @param aRes The result handler. - */ - void RegisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes); - - /** - * Sends an UnregisterModule command to the Sensors daemon. The service - * should not be used afterwards until it has been registered again. - * - * @param aId The id of the service that is to be unregistered. - * @param aRes The result handler. - */ - void UnregisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes); - -private: - void DispatchError(GonkSensorsRegistryResultHandler* aRes, - SensorsError aError); - void DispatchError(GonkSensorsRegistryResultHandler* aRes, - nsresult aRv); - - GonkSensorsRegistryModule* mModule; -}; - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsRegistryInterface_h diff --git a/hal/gonk/GonkSwitch.cpp b/hal/gonk/GonkSwitch.cpp deleted file mode 100644 index b2c31c973..000000000 --- a/hal/gonk/GonkSwitch.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <fcntl.h> -#include <sysutils/NetlinkEvent.h> - -#include "base/message_loop.h" -#include "base/task.h" - -#include "Hal.h" -#include "HalLog.h" -#include "mozilla/FileUtils.h" -#include "mozilla/RefPtr.h" -#include "mozilla/Monitor.h" -#include "nsPrintfCString.h" -#include "nsXULAppAPI.h" -#include "nsThreadUtils.h" -#include "UeventPoller.h" - -using namespace mozilla::hal; - -#define SWITCH_HEADSET_DEVPATH "/devices/virtual/switch/h2w" -#define SWITCH_USB_DEVPATH_GB "/devices/virtual/switch/usb_configuration" -#define SWITCH_USB_DEVPATH_ICS "/devices/virtual/android_usb/android0" - -namespace mozilla { -namespace hal_impl { -/** - * The uevent for a usb on GB insertion looks like: - * - * change@/devices/virtual/switch/usb_configuration - * ACTION=change - * DEVPATH=/devices/virtual/switch/usb_configuration - * SUBSYSTEM=switch - * SWITCH_NAME=usb_configuration - * SWITCH_STATE=0 - * SEQNUM=5038 - */ -class SwitchHandler -{ -public: - NS_INLINE_DECL_REFCOUNTING(SwitchHandler) - - SwitchHandler(const char* aDevPath, SwitchDevice aDevice) - : mDevPath(aDevPath), - mState(SWITCH_STATE_UNKNOWN), - mDevice(aDevice) - { - GetInitialState(); - } - - bool CheckEvent(NetlinkEvent* aEvent) - { - if (strcmp(GetSubsystem(), aEvent->getSubsystem()) || - strcmp(mDevPath, aEvent->findParam("DEVPATH"))) { - return false; - } - - mState = ConvertState(GetStateString(aEvent)); - return mState != SWITCH_STATE_UNKNOWN; - } - - SwitchState GetState() - { - return mState; - } - - SwitchDevice GetType() - { - return mDevice; - } -protected: - virtual ~SwitchHandler() - { - } - - virtual const char* GetSubsystem() - { - return "switch"; - } - - virtual const char* GetStateString(NetlinkEvent* aEvent) - { - return aEvent->findParam("SWITCH_STATE"); - } - - void GetInitialState() - { - nsPrintfCString statePath("/sys%s/state", mDevPath); - int fd = open(statePath.get(), O_RDONLY); - if (fd <= 0) { - return; - } - - ScopedClose autoClose(fd); - char state[16]; - ssize_t bytesRead = read(fd, state, sizeof(state)); - if (bytesRead < 0) { - HAL_ERR("Read data from %s fails", statePath.get()); - return; - } - - if (state[bytesRead - 1] == '\n') { - bytesRead--; - } - - state[bytesRead] = '\0'; - mState = ConvertState(state); - } - - virtual SwitchState ConvertState(const char* aState) - { - MOZ_ASSERT(aState); - return aState[0] == '0' ? SWITCH_STATE_OFF : SWITCH_STATE_ON; - } - - const char* mDevPath; - SwitchState mState; - SwitchDevice mDevice; -}; - -/** - * The uevent delivered for the USB configuration under ICS looks like, - * - * change@/devices/virtual/android_usb/android0 - * ACTION=change - * DEVPATH=/devices/virtual/android_usb/android0 - * SUBSYSTEM=android_usb - * USB_STATE=CONFIGURED - * SEQNUM=1802 - */ -class SwitchHandlerUsbIcs: public SwitchHandler -{ -public: - SwitchHandlerUsbIcs(const char* aDevPath) : SwitchHandler(aDevPath, SWITCH_USB) - { - SwitchHandler::GetInitialState(); - } - - virtual ~SwitchHandlerUsbIcs() { } - -protected: - virtual const char* GetSubsystem() - { - return "android_usb"; - } - - virtual const char* GetStateString(NetlinkEvent* aEvent) - { - return aEvent->findParam("USB_STATE"); - } - - SwitchState ConvertState(const char* aState) - { - MOZ_ASSERT(aState); - return strcmp(aState, "CONFIGURED") == 0 ? SWITCH_STATE_ON : SWITCH_STATE_OFF; - } -}; - -/** - * The uevent delivered for the headset under ICS looks like, - * - * change@/devices/virtual/switch/h2w - * ACTION=change - * DEVPATH=/devices/virtual/switch/h2w - * SUBSYSTEM=switch - * SWITCH_NAME=h2w - * SWITCH_STATE=2 // Headset with no mic - * SEQNUM=2581 - * On Otoro, SWITCH_NAME could be Headset/No Device when plug/unplug. - * change@/devices/virtual/switch/h2w - * ACTION=change - * DEVPATH=/devices/virtual/switch/h2w - * SUBSYSTEM=switch - * SWITCH_NAME=Headset - * SWITCH_STATE=1 // Headset with mic - * SEQNUM=1602 - */ -class SwitchHandlerHeadphone: public SwitchHandler -{ -public: - SwitchHandlerHeadphone(const char* aDevPath) : - SwitchHandler(aDevPath, SWITCH_HEADPHONES) - { - SwitchHandler::GetInitialState(); - } - - virtual ~SwitchHandlerHeadphone() { } - -protected: - SwitchState ConvertState(const char* aState) - { - MOZ_ASSERT(aState); - - return aState[0] == '0' ? SWITCH_STATE_OFF : - (aState[0] == '1' ? SWITCH_STATE_HEADSET : SWITCH_STATE_HEADPHONE); - } -}; - - -typedef nsTArray<RefPtr<SwitchHandler> > SwitchHandlerArray; - -class SwitchEventRunnable : public Runnable -{ -public: - SwitchEventRunnable(SwitchEvent& aEvent) : mEvent(aEvent) - { - } - - NS_IMETHOD Run() override - { - NotifySwitchChange(mEvent); - return NS_OK; - } -private: - SwitchEvent mEvent; -}; - -class SwitchEventObserver final : public IUeventObserver -{ - ~SwitchEventObserver() - { - mHandler.Clear(); - } - -public: - NS_INLINE_DECL_REFCOUNTING(SwitchEventObserver) - SwitchEventObserver() - : mEnableCount(0), - mHeadphonesFromInputDev(false) - { - Init(); - } - - int GetEnableCount() - { - return mEnableCount; - } - - void EnableSwitch(SwitchDevice aDevice) - { - mEventInfo[aDevice].mEnabled = true; - mEnableCount++; - } - - void DisableSwitch(SwitchDevice aDevice) - { - mEventInfo[aDevice].mEnabled = false; - mEnableCount--; - } - - void Notify(const NetlinkEvent& aEvent) - { - SwitchState currState; - - SwitchDevice device = GetEventInfo(aEvent, currState); - if (device == SWITCH_DEVICE_UNKNOWN) { - return; - } - - EventInfo& info = mEventInfo[device]; - if (currState == info.mEvent.status()) { - return; - } - - info.mEvent.status() = currState; - - if (info.mEnabled) { - NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent)); - } - } - - void Notify(SwitchDevice aDevice, SwitchState aState) - { - EventInfo& info = mEventInfo[aDevice]; - if (aState == info.mEvent.status()) { - return; - } - - info.mEvent.status() = aState; - - if (info.mEnabled) { - NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent)); - } - } - - SwitchState GetCurrentInformation(SwitchDevice aDevice) - { - return mEventInfo[aDevice].mEvent.status(); - } - - void NotifyAnEvent(SwitchDevice aDevice) - { - EventInfo& info = mEventInfo[aDevice]; - if (info.mEvent.status() != SWITCH_STATE_UNKNOWN) { - NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent)); - } - } - - bool GetHeadphonesFromInputDev() - { - return mHeadphonesFromInputDev; - } - -private: - class EventInfo - { - public: - EventInfo() : mEnabled(false) - { - mEvent.status() = SWITCH_STATE_UNKNOWN; - mEvent.device() = SWITCH_DEVICE_UNKNOWN; - } - SwitchEvent mEvent; - bool mEnabled; - }; - - EventInfo mEventInfo[NUM_SWITCH_DEVICE]; - size_t mEnableCount; - SwitchHandlerArray mHandler; - bool mHeadphonesFromInputDev; - - // This function might also get called on the main thread - // (from IsHeadphoneEventFromInputDev) - void Init() - { - RefPtr<SwitchHandlerHeadphone> switchHeadPhone = - new SwitchHandlerHeadphone(SWITCH_HEADSET_DEVPATH); - - // If the initial state is unknown, it means the headphone event is from input dev - mHeadphonesFromInputDev = switchHeadPhone->GetState() == SWITCH_STATE_UNKNOWN ? true : false; - - if (!mHeadphonesFromInputDev) { - mHandler.AppendElement(switchHeadPhone); - } else { - // If headphone status will be notified from input dev then initialize - // status to "off" and wait for event notification. - mEventInfo[SWITCH_HEADPHONES].mEvent.device() = SWITCH_HEADPHONES; - mEventInfo[SWITCH_HEADPHONES].mEvent.status() = SWITCH_STATE_OFF; - } - mHandler.AppendElement(new SwitchHandler(SWITCH_USB_DEVPATH_GB, SWITCH_USB)); - mHandler.AppendElement(new SwitchHandlerUsbIcs(SWITCH_USB_DEVPATH_ICS)); - - SwitchHandlerArray::index_type handlerIndex; - SwitchHandlerArray::size_type numHandlers = mHandler.Length(); - - for (handlerIndex = 0; handlerIndex < numHandlers; handlerIndex++) { - SwitchState state = mHandler[handlerIndex]->GetState(); - if (state == SWITCH_STATE_UNKNOWN) { - continue; - } - - SwitchDevice device = mHandler[handlerIndex]->GetType(); - mEventInfo[device].mEvent.device() = device; - mEventInfo[device].mEvent.status() = state; - } - } - - SwitchDevice GetEventInfo(const NetlinkEvent& aEvent, SwitchState& aState) - { - //working around the android code not being const-correct - NetlinkEvent *e = const_cast<NetlinkEvent*>(&aEvent); - - for (size_t i = 0; i < mHandler.Length(); i++) { - if (mHandler[i]->CheckEvent(e)) { - aState = mHandler[i]->GetState(); - return mHandler[i]->GetType(); - } - } - return SWITCH_DEVICE_UNKNOWN; - } -}; - -static RefPtr<SwitchEventObserver> sSwitchObserver; - -static void -InitializeResourceIfNeed() -{ - if (!sSwitchObserver) { - sSwitchObserver = new SwitchEventObserver(); - RegisterUeventListener(sSwitchObserver); - } -} - -static void -ReleaseResourceIfNeed() -{ - if (sSwitchObserver->GetEnableCount() == 0) { - UnregisterUeventListener(sSwitchObserver); - sSwitchObserver = nullptr; - } -} - -static void -EnableSwitchNotificationsIOThread(SwitchDevice aDevice, Monitor *aMonitor) -{ - InitializeResourceIfNeed(); - sSwitchObserver->EnableSwitch(aDevice); - { - MonitorAutoLock lock(*aMonitor); - lock.Notify(); - } - - // Notify the latest state if IO thread has the information. - if (sSwitchObserver->GetEnableCount() > 1) { - sSwitchObserver->NotifyAnEvent(aDevice); - } -} - -void -EnableSwitchNotifications(SwitchDevice aDevice) -{ - Monitor monitor("EnableSwitch.monitor"); - { - MonitorAutoLock lock(monitor); - XRE_GetIOMessageLoop()->PostTask( - NewRunnableFunction(EnableSwitchNotificationsIOThread, aDevice, &monitor)); - lock.Wait(); - } -} - -static void -DisableSwitchNotificationsIOThread(SwitchDevice aDevice) -{ - MOZ_ASSERT(sSwitchObserver->GetEnableCount()); - sSwitchObserver->DisableSwitch(aDevice); - ReleaseResourceIfNeed(); -} - -void -DisableSwitchNotifications(SwitchDevice aDevice) -{ - XRE_GetIOMessageLoop()->PostTask( - NewRunnableFunction(DisableSwitchNotificationsIOThread, aDevice)); -} - -SwitchState -GetCurrentSwitchState(SwitchDevice aDevice) -{ - MOZ_ASSERT(sSwitchObserver && sSwitchObserver->GetEnableCount()); - return sSwitchObserver->GetCurrentInformation(aDevice); -} - -static void -NotifySwitchStateIOThread(SwitchDevice aDevice, SwitchState aState) -{ - InitializeResourceIfNeed(); - sSwitchObserver->Notify(aDevice, aState); -} - -void NotifySwitchStateFromInputDevice(SwitchDevice aDevice, SwitchState aState) -{ - XRE_GetIOMessageLoop()->PostTask( - NewRunnableFunction(NotifySwitchStateIOThread, aDevice, aState)); -} - -bool IsHeadphoneEventFromInputDev() -{ - // Instead of calling InitializeResourceIfNeed, create new SwitchEventObserver - // to prevent calling RegisterUeventListener in main thread. - RefPtr<SwitchEventObserver> switchObserver = new SwitchEventObserver(); - return switchObserver->GetHeadphonesFromInputDev(); -} - -} // hal_impl -} //mozilla diff --git a/hal/gonk/SensorsTypes.h b/hal/gonk/SensorsTypes.h deleted file mode 100644 index 35c852f5a..000000000 --- a/hal/gonk/SensorsTypes.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#ifndef hal_gonk_SensorsTypes_h -#define hal_gonk_SensorsTypes_h - -namespace mozilla { -namespace hal { - -enum SensorsDeliveryMode { - SENSORS_DELIVERY_MODE_BEST_EFFORT, - SENSORS_DELIVERY_MODE_IMMEDIATE -}; - -enum SensorsError { - SENSORS_ERROR_NONE, - SENSORS_ERROR_FAIL, - SENSORS_ERROR_NOT_READY, - SENSORS_ERROR_NOMEM, - SENSORS_ERROR_BUSY, - SENSORS_ERROR_DONE, - SENSORS_ERROR_UNSUPPORTED, - SENSORS_ERROR_PARM_INVALID -}; - -enum SensorsStatus { - SENSORS_STATUS_NO_CONTACT, - SENSORS_STATUS_UNRELIABLE, - SENSORS_STATUS_ACCURACY_LOW, - SENSORS_STATUS_ACCURACY_MEDIUM, - SENSORS_STATUS_ACCURACY_HIGH -}; - -enum SensorsTriggerMode { - SENSORS_TRIGGER_MODE_CONTINUOUS, - SENSORS_TRIGGER_MODE_ON_CHANGE, - SENSORS_TRIGGER_MODE_ONE_SHOT, - SENSORS_TRIGGER_MODE_SPECIAL -}; - -enum SensorsType { - SENSORS_TYPE_ACCELEROMETER, - SENSORS_TYPE_GEOMAGNETIC_FIELD, - SENSORS_TYPE_ORIENTATION, - SENSORS_TYPE_GYROSCOPE, - SENSORS_TYPE_LIGHT, - SENSORS_TYPE_PRESSURE, - SENSORS_TYPE_TEMPERATURE, - SENSORS_TYPE_PROXIMITY, - SENSORS_TYPE_GRAVITY, - SENSORS_TYPE_LINEAR_ACCELERATION, - SENSORS_TYPE_ROTATION_VECTOR, - SENSORS_TYPE_RELATIVE_HUMIDITY, - SENSORS_TYPE_AMBIENT_TEMPERATURE, - SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED, - SENSORS_TYPE_GAME_ROTATION_VECTOR, - SENSORS_TYPE_GYROSCOPE_UNCALIBRATED, - SENSORS_TYPE_SIGNIFICANT_MOTION, - SENSORS_TYPE_STEP_DETECTED, - SENSORS_TYPE_STEP_COUNTER, - SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR, - SENSORS_TYPE_HEART_RATE, - SENSORS_TYPE_TILT_DETECTOR, - SENSORS_TYPE_WAKE_GESTURE, - SENSORS_TYPE_GLANCE_GESTURE, - SENSORS_TYPE_PICK_UP_GESTURE, - SENSORS_TYPE_WRIST_TILT_GESTURE, - SENSORS_NUM_TYPES -}; - -struct SensorsEvent { - SensorsType mType; - SensorsStatus mStatus; - SensorsDeliveryMode mDeliveryMode; - int64_t mTimestamp; - union { - float mFloat[6]; - uint64_t mUint[1]; - } mData; -}; - -/** - * |SensorsSensor| represents a device sensor; either single or composite. - */ -struct SensorsSensor { - SensorsSensor(int32_t aId, SensorsType aType, - float aRange, float aResolution, - float aPower, int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode) - : mId(aId) - , mType(aType) - , mRange(aRange) - , mResolution(aResolution) - , mPower(aPower) - , mMinPeriod(aMinPeriod) - , mMaxPeriod(aMaxPeriod) - , mTriggerMode(aTriggerMode) - , mDeliveryMode(aDeliveryMode) - { } - - int32_t mId; - SensorsType mType; - float mRange; - float mResolution; - float mPower; - int32_t mMinPeriod; - int32_t mMaxPeriod; - SensorsTriggerMode mTriggerMode; - SensorsDeliveryMode mDeliveryMode; -}; - -/** - * |SensorClass| represents the status of a specific sensor type. - */ -struct SensorsSensorClass { - SensorsSensorClass() - : mActivated(0) - , mMinValue(0) - , mMaxValue(0) - { } - - void UpdateFromSensor(const SensorsSensor& aSensor) - { - mMaxValue = std::max(aSensor.mRange, mMaxValue); - } - - uint32_t mActivated; - float mMinValue; - float mMaxValue; -}; - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_SensorsTypes_h diff --git a/hal/gonk/SystemService.cpp b/hal/gonk/SystemService.cpp deleted file mode 100644 index 2b98f5fdd..000000000 --- a/hal/gonk/SystemService.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- 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 "Hal.h" - -#include <cutils/properties.h> -#include <stdio.h> -#include <string.h> - -#include "HalLog.h" -#include "nsITimer.h" -#include "mozilla/Unused.h" - -namespace mozilla { -namespace hal_impl { - -static const int sRetryInterval = 100; // ms - -bool -SystemServiceIsRunning(const char* aSvcName) -{ - MOZ_ASSERT(NS_IsMainThread()); - - char key[PROPERTY_KEY_MAX]; - auto res = snprintf(key, sizeof(key), "init.svc.%s", aSvcName); - - if (res < 0) { - HAL_ERR("snprintf: %s", strerror(errno)); - return false; - } else if (static_cast<size_t>(res) >= sizeof(key)) { - HAL_ERR("snprintf: trunctated service name %s", aSvcName); - return false; - } - - char value[PROPERTY_VALUE_MAX]; - Unused << NS_WARN_IF(property_get(key, value, "") < 0); - - return !strcmp(value, "running"); -} - -class StartSystemServiceTimerCallback final : public nsITimerCallback -{ - NS_DECL_THREADSAFE_ISUPPORTS; - -public: - StartSystemServiceTimerCallback(const char* aSvcName, const char* aArgs) - : mSvcName(aSvcName) - , mArgs(aArgs) - { - MOZ_COUNT_CTOR_INHERITED(StartSystemServiceTimerCallback, - nsITimerCallback); - } - - NS_IMETHOD Notify(nsITimer* aTimer) override - { - MOZ_ASSERT(NS_IsMainThread()); - - return StartSystemService(mSvcName.get(), mArgs.get()); - } - -protected: - ~StartSystemServiceTimerCallback() - { - MOZ_COUNT_DTOR_INHERITED(StartSystemServiceTimerCallback, - nsITimerCallback); - } - -private: - nsCString mSvcName; - nsCString mArgs; -}; - -NS_IMPL_ISUPPORTS0(StartSystemServiceTimerCallback); - -nsresult -StartSystemService(const char* aSvcName, const char* aArgs) -{ - MOZ_ASSERT(NS_IsMainThread()); - - char value[PROPERTY_VALUE_MAX]; - auto res = snprintf(value, sizeof(value), "%s:%s", aSvcName, aArgs); - - if (res < 0) { - HAL_ERR("snprintf: %s", strerror(errno)); - return NS_ERROR_FAILURE; - } else if (static_cast<size_t>(res) >= sizeof(value)) { - HAL_ERR("snprintf: trunctated service name %s", aSvcName); - return NS_ERROR_OUT_OF_MEMORY; - } - - if (NS_WARN_IF(property_set("ctl.start", value) < 0)) { - return NS_ERROR_FAILURE; - } - - /* If the system service is not running, re-try later to start it. - * - * This condition happens when we restart a service immediately - * after it crashed, as the service state remains 'stopping' - * instead of 'stopped'. Due to the limitation of property service, - * hereby add delay. See Bug 1143925 Comment 41. - */ - if (!SystemServiceIsRunning(aSvcName)) { - nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1"); - if (!timer) { - return NS_ERROR_FAILURE; - } - - RefPtr<StartSystemServiceTimerCallback> timerCallback = - new StartSystemServiceTimerCallback(aSvcName, aArgs); - - timer->InitWithCallback(timerCallback, - sRetryInterval, - nsITimer::TYPE_ONE_SHOT); - } - - return NS_OK; -} - -void -StopSystemService(const char* aSvcName) -{ - MOZ_ASSERT(NS_IsMainThread()); - - Unused << NS_WARN_IF(property_set("ctl.stop", aSvcName)); -} - -} // namespace hal_impl -} // namespace mozilla diff --git a/hal/gonk/UeventPoller.cpp b/hal/gonk/UeventPoller.cpp deleted file mode 100644 index 3fbe850ed..000000000 --- a/hal/gonk/UeventPoller.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <signal.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> - -#include <arpa/inet.h> -#include <linux/types.h> -#include <linux/netlink.h> -#include <netinet/in.h> -#include <sys/socket.h> - -#include "HalLog.h" -#include "nsDebug.h" -#include "base/message_loop.h" -#include "base/task.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/FileUtils.h" -#include "mozilla/Monitor.h" -#include "nsThreadUtils.h" -#include "nsXULAppAPI.h" - -#include "UeventPoller.h" - -using namespace mozilla; - -namespace mozilla { -namespace hal_impl { - -static void ShutdownUevent(); - -class NetlinkPoller : public MessageLoopForIO::Watcher -{ -public: - NetlinkPoller() : mSocket(-1), - mIOLoop(MessageLoopForIO::current()) - { - } - - virtual ~NetlinkPoller() {} - - bool OpenSocket(); - - virtual void OnFileCanReadWithoutBlocking(int fd); - - // no writing to the netlink socket - virtual void OnFileCanWriteWithoutBlocking(int fd) - { - MOZ_CRASH("Must not write to netlink socket"); - } - - MessageLoopForIO *GetIOLoop () const { return mIOLoop; } - void RegisterObserver(IUeventObserver *aObserver) - { - mUeventObserverList.AddObserver(aObserver); - } - - void UnregisterObserver(IUeventObserver *aObserver) - { - mUeventObserverList.RemoveObserver(aObserver); - if (mUeventObserverList.Length() == 0) { - ShutdownUevent(); // this will destroy self - } - } - -private: - ScopedClose mSocket; - MessageLoopForIO* mIOLoop; - MessageLoopForIO::FileDescriptorWatcher mReadWatcher; - - const static int kBuffsize = 64 * 1024; - uint8_t mBuffer [kBuffsize]; - - typedef ObserverList<NetlinkEvent> UeventObserverList; - UeventObserverList mUeventObserverList; -}; - -bool -NetlinkPoller::OpenSocket() -{ - mSocket.rwget() = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); - if (mSocket.get() < 0) { - return false; - } - - int sz = kBuffsize; - - if (setsockopt(mSocket.get(), SOL_SOCKET, SO_RCVBUFFORCE, &sz, - sizeof(sz)) < 0) { - return false; - } - - // add FD_CLOEXEC flag - int flags = fcntl(mSocket.get(), F_GETFD); - if (flags == -1) { - return false; - } - flags |= FD_CLOEXEC; - if (fcntl(mSocket.get(), F_SETFD, flags) == -1) { - return false; - } - - // set non-blocking - if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) { - return false; - } - - struct sockaddr_nl saddr; - bzero(&saddr, sizeof(saddr)); - saddr.nl_family = AF_NETLINK; - saddr.nl_groups = 1; - saddr.nl_pid = gettid(); - - do { - if (bind(mSocket.get(), (struct sockaddr *)&saddr, sizeof(saddr)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - return false; - } - - if (saddr.nl_pid == 0) { - return false; - } - - // Once there was any other place in the same process assigning saddr.nl_pid by - // gettid(), we can detect it and print warning message. - HAL_LOG("The netlink socket address saddr.nl_pid=%u is in use. " - "Let the kernel re-assign.\n", saddr.nl_pid); - saddr.nl_pid = 0; - } while (true); - - if (!mIOLoop->WatchFileDescriptor(mSocket.get(), - true, - MessageLoopForIO::WATCH_READ, - &mReadWatcher, - this)) { - return false; - } - - return true; -} - -static StaticAutoPtr<NetlinkPoller> sPoller; - -class UeventInitTask : public Runnable -{ - NS_IMETHOD Run() override - { - if (!sPoller) { - return NS_OK; - } - if (sPoller->OpenSocket()) { - return NS_OK; - } - sPoller->GetIOLoop()->PostDelayedTask(MakeAndAddRef<UeventInitTask>(), - 1000); - return NS_OK; - } -}; - -void -NetlinkPoller::OnFileCanReadWithoutBlocking(int fd) -{ - MOZ_ASSERT(fd == mSocket.get()); - while (true) { - int ret = read(fd, mBuffer, kBuffsize); - if (ret == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - return; - } - if (errno == EINTR) { - continue; - } - } - if (ret <= 0) { - // fatal error on netlink socket which should not happen - _exit(1); - } - NetlinkEvent netlinkEvent; - netlinkEvent.decode(reinterpret_cast<char*>(mBuffer), ret); - mUeventObserverList.Broadcast(netlinkEvent); - } -} - -static bool sShutdown = false; - -class ShutdownNetlinkPoller; -static StaticAutoPtr<ShutdownNetlinkPoller> sShutdownPoller; -static Monitor* sMonitor = nullptr; - -class ShutdownNetlinkPoller { -public: - ~ShutdownNetlinkPoller() - { - // This is called from KillClearOnShutdown() on the main thread. - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(XRE_GetIOMessageLoop()); - - { - MonitorAutoLock lock(*sMonitor); - - XRE_GetIOMessageLoop()->PostTask( - NewRunnableFunction(ShutdownUeventIOThread)); - - while (!sShutdown) { - lock.Wait(); - } - } - - sShutdown = true; - delete sMonitor; - } - - static void MaybeInit() - { - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - if (sShutdown || sMonitor) { - // Don't init twice or init after shutdown. - return; - } - - sMonitor = new Monitor("ShutdownNetlinkPoller.monitor"); - { - ShutdownNetlinkPoller* shutdownPoller = new ShutdownNetlinkPoller(); - - nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=] () -> void - { - sShutdownPoller = shutdownPoller; - ClearOnShutdown(&sShutdownPoller); // Must run on the main thread. - }); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS( - NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)); - } - } -private: - ShutdownNetlinkPoller() = default; - static void ShutdownUeventIOThread() - { - MonitorAutoLock l(*sMonitor); - ShutdownUevent(); // Must run on the IO thread. - sShutdown = true; - l.NotifyAll(); - } -}; - -static void -InitializeUevent() -{ - MOZ_ASSERT(!sPoller); - sPoller = new NetlinkPoller(); - sPoller->GetIOLoop()->PostTask(MakeAndAddRef<UeventInitTask>()); - - ShutdownNetlinkPoller::MaybeInit(); -} - -static void -ShutdownUevent() -{ - sPoller = nullptr; -} - -void -RegisterUeventListener(IUeventObserver *aObserver) -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - - if (sShutdown) { - return; - } - - if (!sPoller) { - InitializeUevent(); - } - sPoller->RegisterObserver(aObserver); -} - -void -UnregisterUeventListener(IUeventObserver *aObserver) -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - - if (sShutdown) { - return; - } - - sPoller->UnregisterObserver(aObserver); -} - -} // hal_impl -} // mozilla - diff --git a/hal/gonk/UeventPoller.h b/hal/gonk/UeventPoller.h deleted file mode 100644 index ba121cec2..000000000 --- a/hal/gonk/UeventPoller.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _mozilla_uevent_poller_h_ -#define _mozilla_uevent_poller_h_ - -#include <sysutils/NetlinkEvent.h> -#include "mozilla/Observer.h" - -class NetlinkEvent; - -namespace mozilla { -namespace hal_impl { - -typedef mozilla::Observer<NetlinkEvent> IUeventObserver; - -/** - * Register for uevent notification. Note that the method should run on the - * <b> IO Thread </b> - * @aObserver the observer to be added. The observer's Notify() is only called - * on the <b> IO Thread </b> - */ -void RegisterUeventListener(IUeventObserver *aObserver); - -/** - * Unregister for uevent notification. Note that the method should run on the - * <b> IO Thread </b> - * @aObserver the observer to be removed - */ -void UnregisterUeventListener(IUeventObserver *aObserver); - -} -} - -#endif - diff --git a/hal/gonk/fanotify.h b/hal/gonk/fanotify.h deleted file mode 100644 index e715d3bf9..000000000 --- a/hal/gonk/fanotify.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef _LINUX_FANOTIFY_H -#define _LINUX_FANOTIFY_H - -/* This is a Linux header generated by "make headers_install" */ - -#include <linux/types.h> - -/* the following events that user-space can register for */ -#define FAN_ACCESS 0x00000001 /* File was accessed */ -#define FAN_MODIFY 0x00000002 /* File was modified */ -#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */ -#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ -#define FAN_OPEN 0x00000020 /* File was opened */ - -#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ - -#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ -#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ - -#define FAN_ONDIR 0x40000000 /* event occurred against dir */ - -#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ - -/* helper events */ -#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ - -/* flags used for fanotify_init() */ -#define FAN_CLOEXEC 0x00000001 -#define FAN_NONBLOCK 0x00000002 - -/* These are NOT bitwise flags. Both bits are used togther. */ -#define FAN_CLASS_NOTIF 0x00000000 -#define FAN_CLASS_CONTENT 0x00000004 -#define FAN_CLASS_PRE_CONTENT 0x00000008 -#define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ - FAN_CLASS_PRE_CONTENT) - -#define FAN_UNLIMITED_QUEUE 0x00000010 -#define FAN_UNLIMITED_MARKS 0x00000020 - -#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ - FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\ - FAN_UNLIMITED_MARKS) - -/* flags used for fanotify_modify_mark() */ -#define FAN_MARK_ADD 0x00000001 -#define FAN_MARK_REMOVE 0x00000002 -#define FAN_MARK_DONT_FOLLOW 0x00000004 -#define FAN_MARK_ONLYDIR 0x00000008 -#define FAN_MARK_MOUNT 0x00000010 -#define FAN_MARK_IGNORED_MASK 0x00000020 -#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 -#define FAN_MARK_FLUSH 0x00000080 - -#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ - FAN_MARK_REMOVE |\ - FAN_MARK_DONT_FOLLOW |\ - FAN_MARK_ONLYDIR |\ - FAN_MARK_MOUNT |\ - FAN_MARK_IGNORED_MASK |\ - FAN_MARK_IGNORED_SURV_MODIFY |\ - FAN_MARK_FLUSH) - -/* - * All of the events - we build the list by hand so that we can add flags in - * the future and not break backward compatibility. Apps will get only the - * events that they originally wanted. Be sure to add new events here! - */ -#define FAN_ALL_EVENTS (FAN_ACCESS |\ - FAN_MODIFY |\ - FAN_CLOSE |\ - FAN_OPEN) - -/* - * All events which require a permission response from userspace - */ -#define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\ - FAN_ACCESS_PERM) - -#define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\ - FAN_ALL_PERM_EVENTS |\ - FAN_Q_OVERFLOW) - -#define FANOTIFY_METADATA_VERSION 3 - -struct fanotify_event_metadata { - __u32 event_len; - __u8 vers; - __u8 reserved; - __u16 metadata_len; - __u64 mask; - __s32 fd; - __s32 pid; -}; - -struct fanotify_response { - __s32 fd; - __u32 response; -}; - -/* Legit userspace responses to a _PERM event */ -#define FAN_ALLOW 0x01 -#define FAN_DENY 0x02 -/* No fd set in event */ -#define FAN_NOFD -1 - -/* Helper functions to deal with fanotify_event_metadata buffers */ -#define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata)) - -#define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \ - (struct fanotify_event_metadata*)(((char *)(meta)) + \ - (meta)->event_len)) - -#define FAN_EVENT_OK(meta, len) ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \ - (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \ - (long)(meta)->event_len <= (long)(len)) - -#endif /* _LINUX_FANOTIFY_H */ diff --git a/hal/gonk/nsIRecoveryService.idl b/hal/gonk/nsIRecoveryService.idl deleted file mode 100644 index ecbb39c0e..000000000 --- a/hal/gonk/nsIRecoveryService.idl +++ /dev/null @@ -1,39 +0,0 @@ -/* 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 "nsISupports.idl" - -[scriptable, uuid(bc24fb33-a0c1-49ca-aa43-05f167e02fb6)] -interface nsIRecoveryService : nsISupports -{ - /** - * Possible values of fotaStatus.result. These should stay in sync with - * librecovery/librecovery.h - */ - const long FOTA_UPDATE_UNKNOWN = 0; - const long FOTA_UPDATE_FAIL = 1; - const long FOTA_UPDATE_SUCCESS = 2; - - /** - * Uses recovery to wipe the data and cache partitions. If this call is - * successful, the device should reboot before the function call ever returns. - * - * @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason. - */ - void factoryReset(in string reason); - - /** - * Use recovery to install an OTA update.zip. If this call is - * successful, the device should reboot before the function call ever returns. - * - * @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason. - */ - void installFotaUpdate(in string updatePath); - - /** - * @return The status of the last FOTA update. One of FOTA_UPDATE_UNKNOWN, - * FOTA_UPDATE_FAIL, FOTA_UPDATE_SUCCESS. - */ - long getFotaUpdateStatus(); -}; diff --git a/hal/gonk/tavarua.h b/hal/gonk/tavarua.h deleted file mode 100644 index 4eb3483a8..000000000 --- a/hal/gonk/tavarua.h +++ /dev/null @@ -1,484 +0,0 @@ -#ifndef __LINUX_TAVARUA_H -#define __LINUX_TAVARUA_H - -/* This is a Linux header generated by "make headers_install" */ - -#include <stdint.h> -#include <linux/ioctl.h> -#include <linux/videodev2.h> - - -#undef FM_DEBUG - -/* constants */ -#define RDS_BLOCKS_NUM (4) -#define BYTES_PER_BLOCK (3) -#define MAX_PS_LENGTH (96) -#define MAX_RT_LENGTH (64) - -#define XFRDAT0 (0x20) -#define XFRDAT1 (0x21) -#define XFRDAT2 (0x22) - -#define INTDET_PEEK_MSB (0x88) -#define INTDET_PEEK_LSB (0x26) - -#define RMSSI_PEEK_MSB (0x88) -#define RMSSI_PEEK_LSB (0xA8) - -#define MPX_DCC_BYPASS_POKE_MSB (0x88) -#define MPX_DCC_BYPASS_POKE_LSB (0xC0) - -#define MPX_DCC_PEEK_MSB_REG1 (0x88) -#define MPX_DCC_PEEK_LSB_REG1 (0xC2) - -#define MPX_DCC_PEEK_MSB_REG2 (0x88) -#define MPX_DCC_PEEK_LSB_REG2 (0xC3) - -#define MPX_DCC_PEEK_MSB_REG3 (0x88) -#define MPX_DCC_PEEK_LSB_REG3 (0xC4) - -#define ON_CHANNEL_TH_MSB (0x0B) -#define ON_CHANNEL_TH_LSB (0xA8) - -#define OFF_CHANNEL_TH_MSB (0x0B) -#define OFF_CHANNEL_TH_LSB (0xAC) - -#define ENF_200Khz (1) -#define SRCH200KHZ_OFFSET (7) -#define SRCH_MASK (1 << SRCH200KHZ_OFFSET) - -/* Standard buffer size */ -#define STD_BUF_SIZE (128) -/* Search direction */ -#define SRCH_DIR_UP (0) -#define SRCH_DIR_DOWN (1) - -/* control options */ -#define CTRL_ON (1) -#define CTRL_OFF (0) - -#define US_LOW_BAND (87.5) -#define US_HIGH_BAND (108) - -/* constant for Tx */ - -#define MASK_PI (0x0000FFFF) -#define MASK_PI_MSB (0x0000FF00) -#define MASK_PI_LSB (0x000000FF) -#define MASK_PTY (0x0000001F) -#define MASK_TXREPCOUNT (0x0000000F) - -#undef FMDBG -#ifdef FM_DEBUG - #define FMDBG(fmt, args...) printk(KERN_INFO "tavarua_radio: " fmt, ##args) -#else - #define FMDBG(fmt, args...) -#endif - -#undef FMDERR -#define FMDERR(fmt, args...) printk(KERN_INFO "tavarua_radio: " fmt, ##args) - -#undef FMDBG_I2C -#ifdef FM_DEBUG_I2C - #define FMDBG_I2C(fmt, args...) printk(KERN_INFO "fm_i2c: " fmt, ##args) -#else - #define FMDBG_I2C(fmt, args...) -#endif - -/* function declarations */ -/* FM Core audio paths. */ -#define TAVARUA_AUDIO_OUT_ANALOG_OFF (0) -#define TAVARUA_AUDIO_OUT_ANALOG_ON (1) -#define TAVARUA_AUDIO_OUT_DIGITAL_OFF (0) -#define TAVARUA_AUDIO_OUT_DIGITAL_ON (1) - -int tavarua_set_audio_path(int digital_on, int analog_on); - -/* defines and enums*/ - -#define MARIMBA_A0 0x01010013 -#define MARIMBA_2_1 0x02010204 -#define BAHAMA_1_0 0x0302010A -#define BAHAMA_2_0 0x04020205 -#define WAIT_TIMEOUT 2000 -#define RADIO_INIT_TIME 15 -#define TAVARUA_DELAY 10 -/* - * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, - * 62.5 kHz otherwise. - * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. - * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW - * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 - */ -#define FREQ_MUL (1000000 / 62.5) - -enum v4l2_cid_private_tavarua_t { - V4L2_CID_PRIVATE_TAVARUA_SRCHMODE = (V4L2_CID_PRIVATE_BASE + 1), - V4L2_CID_PRIVATE_TAVARUA_SCANDWELL, - V4L2_CID_PRIVATE_TAVARUA_SRCHON, - V4L2_CID_PRIVATE_TAVARUA_STATE, - V4L2_CID_PRIVATE_TAVARUA_TRANSMIT_MODE, - V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK, - V4L2_CID_PRIVATE_TAVARUA_REGION, - V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH, - V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY, - V4L2_CID_PRIVATE_TAVARUA_SRCH_PI, - V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT, - V4L2_CID_PRIVATE_TAVARUA_EMPHASIS, - V4L2_CID_PRIVATE_TAVARUA_RDS_STD, - V4L2_CID_PRIVATE_TAVARUA_SPACING, - V4L2_CID_PRIVATE_TAVARUA_RDSON, - V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC, - V4L2_CID_PRIVATE_TAVARUA_LP_MODE, - V4L2_CID_PRIVATE_TAVARUA_ANTENNA, - V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF, - V4L2_CID_PRIVATE_TAVARUA_PSALL, - /*v4l2 Tx controls*/ - V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT, - V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME, - V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT, - V4L2_CID_PRIVATE_TAVARUA_IOVERC, - V4L2_CID_PRIVATE_TAVARUA_INTDET, - V4L2_CID_PRIVATE_TAVARUA_MPX_DCC, - V4L2_CID_PRIVATE_TAVARUA_AF_JUMP, - V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA, - V4L2_CID_PRIVATE_TAVARUA_HLSI, - - /* - * Here we have IOCTl's that are specific to IRIS - * (V4L2_CID_PRIVATE_BASE + 0x1E to V4L2_CID_PRIVATE_BASE + 0x28) - */ - V4L2_CID_PRIVATE_SOFT_MUTE,/* 0x800001E*/ - V4L2_CID_PRIVATE_RIVA_ACCS_ADDR, - V4L2_CID_PRIVATE_RIVA_ACCS_LEN, - V4L2_CID_PRIVATE_RIVA_PEEK, - V4L2_CID_PRIVATE_RIVA_POKE, - V4L2_CID_PRIVATE_SSBI_ACCS_ADDR, - V4L2_CID_PRIVATE_SSBI_PEEK, - V4L2_CID_PRIVATE_SSBI_POKE, - V4L2_CID_PRIVATE_TX_TONE, - V4L2_CID_PRIVATE_RDS_GRP_COUNTERS, - V4L2_CID_PRIVATE_SET_NOTCH_FILTER,/* 0x8000028 */ - - V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH,/* 0x8000029 */ - V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION,/* 0x800002A : IRIS */ - V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM,/* 0x800002B */ - V4L2_CID_PRIVATE_IRIS_GET_SINR, /* 0x800002C : IRIS */ - V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD, /* 0x800002D */ - V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD, /* 0x800002E */ - V4L2_CID_PRIVATE_SINR_THRESHOLD, /* 0x800002F : IRIS */ - V4L2_CID_PRIVATE_SINR_SAMPLES, /* 0x8000030 : IRIS */ - -}; - -enum tavarua_buf_t { - TAVARUA_BUF_SRCH_LIST, - TAVARUA_BUF_EVENTS, - TAVARUA_BUF_RT_RDS, - TAVARUA_BUF_PS_RDS, - TAVARUA_BUF_RAW_RDS, - TAVARUA_BUF_AF_LIST, - TAVARUA_BUF_MAX -}; - -enum tavarua_xfr_t { - TAVARUA_XFR_SYNC, - TAVARUA_XFR_ERROR, - TAVARUA_XFR_SRCH_LIST, - TAVARUA_XFR_RT_RDS, - TAVARUA_XFR_PS_RDS, - TAVARUA_XFR_AF_LIST, - TAVARUA_XFR_MAX -}; - -enum channel_spacing { - FM_CH_SPACE_200KHZ, - FM_CH_SPACE_100KHZ, - FM_CH_SPACE_50KHZ -}; - -enum step_size { - NO_SRCH200khz, - ENF_SRCH200khz -}; - -enum emphasis { - EMP_75, - EMP_50 -}; - -enum rds_std { - RBDS_STD, - RDS_STD -}; - -/* offsets */ -#define RAW_RDS 0x0F -#define RDS_BLOCK 3 - -/* registers*/ -#define MARIMBA_XO_BUFF_CNTRL 0x07 -#define RADIO_REGISTERS 0x30 -#define XFR_REG_NUM 16 -#define STATUS_REG_NUM 3 - -/* TX constants */ -#define HEADER_SIZE 4 -#define TX_ON 0x80 -#define TAVARUA_TX_RT RDS_RT_0 -#define TAVARUA_TX_PS RDS_PS_0 - -enum register_t { - STATUS_REG1 = 0, - STATUS_REG2, - STATUS_REG3, - RDCTRL, - FREQ, - TUNECTRL, - SRCHRDS1, - SRCHRDS2, - SRCHCTRL, - IOCTRL, - RDSCTRL, - ADVCTRL, - AUDIOCTRL, - RMSSI, - IOVERC, - AUDIOIND = 0x1E, - XFRCTRL, - FM_CTL0 = 0xFF, - LEAKAGE_CNTRL = 0xFE, -}; -#define BAHAMA_RBIAS_CTL1 0x07 -#define BAHAMA_FM_MODE_REG 0xFD -#define BAHAMA_FM_CTL1_REG 0xFE -#define BAHAMA_FM_CTL0_REG 0xFF -#define BAHAMA_FM_MODE_NORMAL 0x00 -#define BAHAMA_LDO_DREG_CTL0 0xF0 -#define BAHAMA_LDO_AREG_CTL0 0xF4 - -/* Radio Control */ -#define RDCTRL_STATE_OFFSET 0 -#define RDCTRL_STATE_MASK (3 << RDCTRL_STATE_OFFSET) -#define RDCTRL_BAND_OFFSET 2 -#define RDCTRL_BAND_MASK (1 << RDCTRL_BAND_OFFSET) -#define RDCTRL_CHSPACE_OFFSET 3 -#define RDCTRL_CHSPACE_MASK (3 << RDCTRL_CHSPACE_OFFSET) -#define RDCTRL_DEEMPHASIS_OFFSET 5 -#define RDCTRL_DEEMPHASIS_MASK (1 << RDCTRL_DEEMPHASIS_OFFSET) -#define RDCTRL_HLSI_OFFSET 6 -#define RDCTRL_HLSI_MASK (3 << RDCTRL_HLSI_OFFSET) -#define RDSAF_OFFSET 6 -#define RDSAF_MASK (1 << RDSAF_OFFSET) - -/* Tune Control */ -#define TUNE_STATION 0x01 -#define ADD_OFFSET (1 << 1) -#define SIGSTATE (1 << 5) -#define MOSTSTATE (1 << 6) -#define RDSSYNC (1 << 7) -/* Search Control */ -#define SRCH_MODE_OFFSET 0 -#define SRCH_MODE_MASK (7 << SRCH_MODE_OFFSET) -#define SRCH_DIR_OFFSET 3 -#define SRCH_DIR_MASK (1 << SRCH_DIR_OFFSET) -#define SRCH_DWELL_OFFSET 4 -#define SRCH_DWELL_MASK (7 << SRCH_DWELL_OFFSET) -#define SRCH_STATE_OFFSET 7 -#define SRCH_STATE_MASK (1 << SRCH_STATE_OFFSET) - -/* I/O Control */ -#define IOC_HRD_MUTE 0x03 -#define IOC_SFT_MUTE (1 << 2) -#define IOC_MON_STR (1 << 3) -#define IOC_SIG_BLND (1 << 4) -#define IOC_INTF_BLND (1 << 5) -#define IOC_ANTENNA (1 << 6) -#define IOC_ANTENNA_OFFSET 6 -#define IOC_ANTENNA_MASK (1 << IOC_ANTENNA_OFFSET) - -/* RDS Control */ -#define RDS_ON 0x01 -#define RDSCTRL_STANDARD_OFFSET 1 -#define RDSCTRL_STANDARD_MASK (1 << RDSCTRL_STANDARD_OFFSET) - -/* Advanced features controls */ -#define RDSRTEN (1 << 3) -#define RDSPSEN (1 << 4) - -/* Audio path control */ -#define AUDIORX_ANALOG_OFFSET 0 -#define AUDIORX_ANALOG_MASK (1 << AUDIORX_ANALOG_OFFSET) -#define AUDIORX_DIGITAL_OFFSET 1 -#define AUDIORX_DIGITAL_MASK (1 << AUDIORX_DIGITAL_OFFSET) -#define AUDIOTX_OFFSET 2 -#define AUDIOTX_MASK (1 << AUDIOTX_OFFSET) -#define I2SCTRL_OFFSET 3 -#define I2SCTRL_MASK (1 << I2SCTRL_OFFSET) - -/* Search options */ -enum search_t { - SEEK, - SCAN, - SCAN_FOR_STRONG, - SCAN_FOR_WEAK, - RDS_SEEK_PTY, - RDS_SCAN_PTY, - RDS_SEEK_PI, - RDS_AF_JUMP, -}; - -enum audio_path { - FM_DIGITAL_PATH, - FM_ANALOG_PATH -}; -#define SRCH_MODE 0x07 -#define SRCH_DIR 0x08 /* 0-up 1-down */ -#define SCAN_DWELL 0x70 -#define SRCH_ON 0x80 - -/* RDS CONFIG */ -#define RDS_CONFIG_PSALL 0x01 - -#define FM_ENABLE 0x22 -#define SET_REG_FIELD(reg, val, offset, mask) \ - (reg = (reg & ~mask) | (((val) << offset) & mask)) -#define GET_REG_FIELD(reg, offset, mask) ((reg & mask) >> offset) -#define RSH_DATA(val, offset) ((val) >> (offset)) -#define LSH_DATA(val, offset) ((val) << (offset)) -#define GET_ABS_VAL(val) ((val) & (0xFF)) - -enum radio_state_t { - FM_OFF, - FM_RECV, - FM_TRANS, - FM_RESET, -}; - -#define XFRCTRL_WRITE (1 << 7) - -/* Interrupt status */ - -/* interrupt register 1 */ -#define READY (1 << 0) /* Radio ready after powerup or reset */ -#define TUNE (1 << 1) /* Tune completed */ -#define SEARCH (1 << 2) /* Search completed (read FREQ) */ -#define SCANNEXT (1 << 3) /* Scanning for next station */ -#define SIGNAL (1 << 4) /* Signal indicator change (read SIGSTATE) */ -#define INTF (1 << 5) /* Interference cnt has fallen outside range */ -#define SYNC (1 << 6) /* RDS sync state change (read RDSSYNC) */ -#define AUDIO (1 << 7) /* Audio Control indicator (read AUDIOIND) */ - -/* interrupt register 2 */ -#define RDSDAT (1 << 0) /* New unread RDS data group available */ -#define BLOCKB (1 << 1) /* Block-B match condition exists */ -#define PROGID (1 << 2) /* Block-A or Block-C matched stored PI value*/ -#define RDSPS (1 << 3) /* New RDS Program Service Table available */ -#define RDSRT (1 << 4) /* New RDS Radio Text available */ -#define RDSAF (1 << 5) /* New RDS AF List available */ -#define TXRDSDAT (1 << 6) /* Transmitted an RDS group */ -#define TXRDSDONE (1 << 7) /* RDS raw group one-shot transmit completed */ - -/* interrupt register 3 */ -#define TRANSFER (1 << 0) /* Data transfer (XFR) completed */ -#define RDSPROC (1 << 1) /* Dynamic RDS Processing complete */ -#define ERROR (1 << 7) /* Err occurred.Read code to determine cause */ - - -#define FM_TX_PWR_LVL_0 0 /* Lowest power lvl that can be set for Tx */ -#define FM_TX_PWR_LVL_MAX 7 /* Max power lvl for Tx */ -/* Transfer */ -enum tavarua_xfr_ctrl_t { - RDS_PS_0 = 0x01, - RDS_PS_1, - RDS_PS_2, - RDS_PS_3, - RDS_PS_4, - RDS_PS_5, - RDS_PS_6, - RDS_RT_0, - RDS_RT_1, - RDS_RT_2, - RDS_RT_3, - RDS_RT_4, - RDS_AF_0, - RDS_AF_1, - RDS_CONFIG, - RDS_TX_GROUPS, - RDS_COUNT_0, - RDS_COUNT_1, - RDS_COUNT_2, - RADIO_CONFIG, - RX_CONFIG, - RX_TIMERS, - RX_STATIONS_0, - RX_STATIONS_1, - INT_CTRL, - ERROR_CODE, - CHIPID, - CAL_DAT_0 = 0x20, - CAL_DAT_1, - CAL_DAT_2, - CAL_DAT_3, - CAL_CFG_0, - CAL_CFG_1, - DIG_INTF_0, - DIG_INTF_1, - DIG_AGC_0, - DIG_AGC_1, - DIG_AGC_2, - DIG_AUDIO_0, - DIG_AUDIO_1, - DIG_AUDIO_2, - DIG_AUDIO_3, - DIG_AUDIO_4, - DIG_RXRDS, - DIG_DCC, - DIG_SPUR, - DIG_MPXDCC, - DIG_PILOT, - DIG_DEMOD, - DIG_MOST, - DIG_TX_0, - DIG_TX_1, - PHY_TXGAIN = 0x3B, - PHY_CONFIG, - PHY_TXBLOCK, - PHY_TCB, - XFR_PEEK_MODE = 0x40, - XFR_POKE_MODE = 0xC0, - TAVARUA_XFR_CTRL_MAX -}; - -enum tavarua_evt_t { - TAVARUA_EVT_RADIO_READY, - TAVARUA_EVT_TUNE_SUCC, - TAVARUA_EVT_SEEK_COMPLETE, - TAVARUA_EVT_SCAN_NEXT, - TAVARUA_EVT_NEW_RAW_RDS, - TAVARUA_EVT_NEW_RT_RDS, - TAVARUA_EVT_NEW_PS_RDS, - TAVARUA_EVT_ERROR, - TAVARUA_EVT_BELOW_TH, - TAVARUA_EVT_ABOVE_TH, - TAVARUA_EVT_STEREO, - TAVARUA_EVT_MONO, - TAVARUA_EVT_RDS_AVAIL, - TAVARUA_EVT_RDS_NOT_AVAIL, - TAVARUA_EVT_NEW_SRCH_LIST, - TAVARUA_EVT_NEW_AF_LIST, - TAVARUA_EVT_TXRDSDAT, - TAVARUA_EVT_TXRDSDONE, - TAVARUA_EVT_RADIO_DISABLED -}; - -enum tavarua_region_t { - TAVARUA_REGION_US, - TAVARUA_REGION_EU, - TAVARUA_REGION_JAPAN, - TAVARUA_REGION_JAPAN_WIDE, - TAVARUA_REGION_OTHER -}; - -#endif /* __LINUX_TAVARUA_H */ |