/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ 'use strict'; var BatteryManager = { TOASTER_TIMEOUT: 5000, TRANSITION_SPEED: 1.8, TRANSITION_FRACTION: 0.30, AUTO_SHUTDOWN_LEVEL: 0.02, EMPTY_BATTERY_LEVEL: 0.1, _battery: window.navigator.battery, _notification: null, getAllElements: function bm_getAllElements() { this.screen = document.getElementById('screen'); this.overlay = document.getElementById('system-overlay'); this.notification = document.getElementById('battery'); }, checkBatteryDrainage: function bm_checkBatteryDrainage() { var battery = this._battery; if (!battery) return; if (battery.level <= this.AUTO_SHUTDOWN_LEVEL) SleepMenu.startPowerOff(false); }, init: function bm_init() { this.getAllElements(); var battery = this._battery; if (battery) { // When the device is booted, check if the battery is drained. // If so, SleepMenu.startPowerOff() would be called. this.checkBatteryDrainage(); battery.addEventListener('levelchange', this); battery.addEventListener('chargingchange', this); } window.addEventListener('screenchange', this); this._toasterGD = new GestureDetector(this.notification); ['mousedown', 'swipe'].forEach(function(evt) { this.notification.addEventListener(evt, this); }, this); this._screenOn = true; this._wasEmptyBatteryNotificationDisplayed = false; this.displayIfNecessary(); }, handleEvent: function bm_handleEvent(evt) { switch (evt.type) { case 'screenchange': this._screenOn = evt.detail.screenEnabled; this.displayIfNecessary(); break; case 'levelchange': var battery = this._battery; if (!battery) return; this.checkBatteryDrainage(); this.displayIfNecessary(); PowerSaveHandler.onBatteryChange(); break; case 'chargingchange': PowerSaveHandler.onBatteryChange(); var battery = this._battery; // We turn the screen on if needed in order to let // the user knows the device is charging if (battery && battery.charging) { this.hide(); this._wasEmptyBatteryNotificationDisplayed = false; if (!this._screenOn) { ScreenManager.turnScreenOn(); } } else { this.displayIfNecessary(); } break; case 'mousedown': this.mousedown(evt); break; case 'swipe': this.swipe(evt); break; } }, _shouldWeDisplay: function bm_shouldWeDisplay() { var battery = this._battery; if (!battery) { return false; } return (!this._wasEmptyBatteryNotificationDisplayed && !battery.charging && battery.level <= this.EMPTY_BATTERY_LEVEL && this._screenOn); }, displayIfNecessary: function bm_display() { if (! this._shouldWeDisplay()) { return; } // we know it's here, it's checked in shouldWeDisplay() var level = this._battery.level; this.overlay.classList.add('battery'); this._toasterGD.startDetecting(); this._wasEmptyBatteryNotificationDisplayed = true; if (this._toasterTimeout) { clearTimeout(this._toasterTimeout); } this._toasterTimeout = setTimeout(this.hide.bind(this), this.TOASTER_TIMEOUT); }, hide: function bm_hide() { var overlayCss = this.overlay.classList; if (overlayCss.contains('battery')) { this.overlay.classList.remove('battery'); this._toasterTimeout = null; this._toasterGD.stopDetecting(); } }, // Swipe handling mousedown: function bm_mousedown(evt) { evt.preventDefault(); this._containerWidth = this.overlay.clientWidth; }, swipe: function bm_swipe(evt) { var detail = evt.detail; var distance = detail.start.screenX - detail.end.screenX; var fastEnough = Math.abs(detail.vx) > this.TRANSITION_SPEED; var farEnough = Math.abs(distance) > this._containerWidth * this.TRANSITION_FRACTION; // If the swipe distance is too short or swipe speed is too slow, // do nothing. if (!(farEnough || fastEnough)) return; var self = this; this.notification.addEventListener('animationend', function animationend() { self.notification.removeEventListener('animationend', animationend); self.notification.classList.remove('disappearing'); self.hide(); }); this.notification.classList.add('disappearing'); } }; var PowerSaveHandler = (function PowerSaveHandler() { var _powerSaveResume = {}; var _powerSaveEnabled = false; var _states = { 'wifi.enabled' : false, 'ril.data.enabled' : false, 'bluetooth.enabled' : false, 'geolocation.enabled' : false }; function init() { SettingsListener.observe('powersave.enabled', false, function sl_getPowerSave(value) { var enabled = value; if (enabled) { enablePowerSave(); } else { disablePowerSave(); } _powerSaveEnabled = enabled; }); // Monitor the states of various modules for (var j in _states) { SettingsListener.observe(j, true, function getState(state, value) { _states[state] = value; }.bind(null, j)); } } // XXX Break down obj keys in a for each loop because mozSettings // does not currently supports multiple keys in one set() // https://bugzilla.mozilla.org/show_bug.cgi?id=779381 function setMozSettings(keypairs) { var setlock = SettingsListener.getSettingsLock(); for (var key in keypairs) { var obj = {}; obj[key] = keypairs[key]; setlock.set(obj); } } function enablePowerSave() { // Keep the original states of various modules for (var j in _states) { _powerSaveResume[j] = _states[j]; } var settingsToSet = { // Turn off Wifi 'wifi.enabled' : false, // Turn off Data 'ril.data.enabled' : false, // Turn off Bluetooth 'bluetooth.enabled' : false, // Turn off Geolocation 'geolocation.enabled' : false }; setMozSettings(settingsToSet); } function disablePowerSave() { var settingsToSet = {}; for (var state in _powerSaveResume) { if (_powerSaveResume[state] == true) settingsToSet[state] = true; } setMozSettings(settingsToSet); } function onBatteryChange() { var battery = BatteryManager._battery; if (battery.charging) { if (_powerSaveEnabled) setMozSettings({'powersave.enabled' : false}); return; } SettingsListener.observe('powersave.threshold', 0, function getThreshold(value) { if (battery.level <= value && !_powerSaveEnabled) { setMozSettings({'powersave.enabled' : true}); return; } if (value != 0 && battery.level > value && _powerSaveEnabled) { setMozSettings({'powersave.enabled' : false}); return; } }); } return { init: init, onBatteryChange: onBatteryChange }; })(); // init PowerSaveHandler first, since it will be used by BatteryManager PowerSaveHandler.init(); BatteryManager.init();