O aplicativo System e o primeiro aplicativo carregado pelo Gecko durante o procedimento de bootup do Firefox OS, e lida com um número grande de responsabilidades que são requeridas para executar o sistema e geralmente não é o escopo dos demais aplicativos. Esse artigo explica em detalhes como o aplicativo System funciona.
Qualquer aplicativo que pode ser escrito em JavaScript acabará sendo escrito em JavaScript. -- Lei de Atwood
Nota: Você pode encontrar o código fonte do aplicativo System no repo do Gaia no Github.
Como o aplicativo system faz o boot
Quando o Gecko tenta iniciar o aplicativo System, ele referencia o manifesto manifest.webapp e carrega o arquivo index.html referenciado pelo parâmetro launch_path
(o launch_path
sempre é o arquivo /index.html para aplicativos Gaia). index.html
conecta a todos os estilos do sistema e JavaScripe. Para gerenciar um sistema móvel completo, o aplicativo System deve carregar um grande número de recursos.
O processo de boot é iniciado pelo programa bootstrap.js
, com o seguinte código:
window.addEventListener('load', function startup() { // define safelyLaunchFTU function safelyLaunchFTU() { ... } if (Applications.ready) { safelyLaunchFTU(); } else { ... } window.addEventListener('ftudone', function doneWithFTU() { window.removeEventListener('ftudone', doneWithFTU); var lock = window.navigator.mozSettings.createLock(); lock.set({ 'gaia.system.checkForUpdates': true }); } ... // With all important event handlers in place, we can now notify // Gecko that we're ready for certain system services to send us // messages (e.g. the radio). var evt = new CustomEvent('mozContentEvent', { bubbles: true, cancelable: false, detail: { type: 'system-message-listener-ready' } }); window.dispatchEvent(evt); }
O código funciona da seguinte maneira:
- O aplicativo System é um aplicativo web real executando num navegador e precisa que todos os recursos dependentes estejam carregados — incluindo as imagens e estilos. Assim, tudo é iniciado de uma só vez pelo
window.onload
. - Primeiro, preparamos para executar o FTU (First Time Experience, ou Primeiro uso) e a tela de início com a função
safelyLaunchFTU()
. Como o nome sugerir, FTU somente é executado quando o usuário inicia o Firefox OS pela primeira vez. - Quando o usuário pressiona DONE dentro do FTU o evento
ftudone
é disparado e o programabootstrap.js
recebe e trabalha esse evento. - No próximo passo, é utilizado a API
Settings
(navigator.mozSettings
) para configurar o parâmetrogaia.system.checkForUpdates
paratrue
, indicando que o sistema irá verificar se há atualizações. - Finalmente, é executado
window.dispatchEvent
, viaCustomEvent
. Isso é um padrão muito importante utilizado pelo Gaia para notificações do sistema e comunicação com o Gecko. Nesse caso, o aplicativo System é notificado pelo Gecko que está pronto para receber e lidar com os eventos.
Modularização instanciável
O próprio sistema está constantemente evoluindo para alcançar a melhor modularização e flexibilidade. A partir da versão 1.4 há uma iniciativa em andamento para refazer o módulo do sistema como um objeto instanciável.
Depois do código abaixo ter sido executado, as referências a cada componente do sistema em bootstrap.js
será da seguinte forma:
window.telephonySettings = new TelephonySettings(); window.telephonySettings.start();
O esqueleto do código fonte para TelephonySettings()
será:
(function(exports) { 'use strict'; function TelephonySettings() { this.init_param = false; } TelephonySettings.prototype = { // Initialzes all settings. start: function() { ... }, // Clean all settings. stop: function() { ... }, 1st_method: function ts_1st_method() { ... }, 2nd_method: function ts_2nd_method() { ... } }; exports.TelephonySettings = TelephonySettings; }(window));
Esse padrão ajuda a modularizar cada componente do sistema e facilita o processo de teste.
Animações do boot e shut down
Essa seção explica como o aplicativo System controla as animações durante o boot e shut down. Os programas init_logo_handler.js
e sleep_menu.js
são os responsáveis por manipular as animações.
Animações de Boot up
A animação do boot up na verdade não está no procedimento principal de bootup, mas pelo EventListeners
.
O código da animação de boot up init_logo_handler.js
parece com isso:
Para desenhar o logo ou a animação uma vez que o Gecko esteja pronto para desenhar algo na tela, nós executamos o manipulador do sistema uma vez que o DOM é carregado, então escondemos o log uma vez que o evento ftudone
ou ftuskip
é disparado. O método _appendCarrierPowerOn
, presente em init_logo_handler.js
, mostra como o Gaia prepara para executar a animação ou mostrar o logo respondendo o evento DOMContentLoaded
event. O logoLoader
é definido em logo_loader.js
.
var self = this; document.addEventListener('DOMContentLoaded', function() { self.carrierLogo.appendChild(self.logoLoader.element); self._setReady(); });
Uma vez que o logo é preparado, o sistema chama o método _setReady()
, que configura um listener para responder a um evento especial mozChromeEvent
com um tipo de system-first-paint
para denotar que o sistema está pronto para desenhar na tela.
var elem = this.logoLoader.element; ... window.addEventListener('mozChromeEvent', function startVideo(e) { if (e.detail.type == 'system-first-paint') { window.removeEventListener('mozChromeEvent', startVideo); if (elem && elem.ended === false) { elem.play(); } } });
Nesse ponto o elemento gráfico entra em ação. Uma vez que o evento ftuopen
ou ftuskip
é disparado, init_logo_handler.js
chama o método handleEvent()
que dispara o método animate()
para terminar a animação com um efeito de transição em fadeout.
init: function ilh_init(logoLoader) { window.addEventListener('ftuopen', this); window.addEventListener('ftuskip', this); ... }, handleEvent: function ilh_handleEvent() { this.animate(); },
Animações de Shut down
Uma vez que o sistema está pronto, uma pressão longa no botão power dispara o evento holdsleep
, como definido no programa hardware_button.js
. Esse script manipula todos os eventos vindos do pressionamento de botões físicos, incluindo o botão power, home, volume para cima e para baixo.
HardwareButtonsSleepState.prototype.enter = function() { this.timer = setTimeout(function() { / * When the user holds Sleep button more than HOLD_INTERVAL. */ this.hardwareButtons.publish('holdsleep'); this.hardwareButtons.setState('base'); }.bind(this), this.hardwareButtons.HOLD_INTERVAL); };
A animação de shut down é manipulada pelo script sleep_menu.js
. Ele responde ao evento holdsleep
e mostra o menu quando é disparado.
init: function sm_init() { ... window.addEventListener('holdsleep', this.show.bind(this)); ... }
Se o usuário escolher desligar ou reiniciar o dispositivo a função startPowerOff()
é chamada que dispara a função LogoLoader()
para manipular a animação de shutdown.
handleEvent: function sm_handleEvent(evt) { switch (evt.type) { case 'click': ... this.handler(action); break; ... } } handler: function sm_handler(action) { switch (action) { ... case 'restart': this.startPowerOff(true); break; case 'power': this.startPowerOff(false); break; ... } }
Funções do sistema
Existe um grande número de funções e responsabilidades gerenciadas pelo aplicativo System, algumas dos quais podem supreender você. O aplicativo System manipula a barra de status e bandeja de utilitários, o travamento do SIM, gerenciador de atualizações, a chamada à tela de início, gerenciador dos aplicativos web e mais. Essa seção explora uma das mais importantes funções providas pelo aplicativo System.
Barra de status e a bandeja de utiliários
A barra de status do sistema e o menu dropdown (Gaia chama isso de utility tray, já no Android é utilizado o termo barra de notificação) são manipulados pelos programas statusbar.js
e utility_tray.js
. Dentro do aplicativo index.html
, a barra de status é definida em <div id="statusbar" data-z-index-level="statusbar">
enquanto que a bandeja de utilitários ficam na seguinte estrutura:
<div id="utility-tray" data-z-index-level="utility-tray"> <div id="notifications-container"> ... </div> </div>
Existem alguns paineis especiais dentro da bandeja de utilitários como o gerenciador de atualização, gerenciador de chamadas de emergência, notificação de armazenamento, controles e notificações do tocador de mídias, status de transferência via bluetooth, troca do IME, ou método de entrada no teclado. Os estilos e gerenciadores relacionados estão nos diretórios js
/ e style/
.
Lançadores especiais de aplicativos
O aplicativo System tem três lançadores especiais, que chamam aplicativos web quando necessário:
- O lançador da tela inicial: Executa o aplicativo Homescreen, que mostra a tela inicial quando o usuário pressiona o botão Home ou se um aplicativo web é encerrado, seja de forma normal ou devido a um erro.
- O lançador da tela bloqueada: Executa o aplicativo Lockscreen, que mostra a tela bloqueada toda vez que o usuário liga a tela.
- O lançador do FTU (Firts time user): Executa o aplicativo FTU experience. Isso é único porque todo usuário verá o resultado desse aplicativo na primeira vez que liga um dispositivo Firefox OS (ou reinicia o dispositivo com as configurações de fábrica). O aplicativo FTU não permite o usuário utilizar o botão Home ou sair do aplicativo.
Tela de bloqueio
O ponto de entrada principal para o aplicativo Lockscreen app é system/js/lockscreen.js
. Dessa tela o usuário pode desbloquear o telefone, chamar a câmera ou controlar o tocador de mídia.
Discagem de emergência
O código para a discagem de emergência está no diretório gaia/apps/system/emergency-call/
. É uma versão simplificada do aplicativo Dialer que possibilita que o usuário acesse do SIM PIN unlock dialog para chamar os serviços de emergência como por exemplo a polícia.
IU (Interface do Usuário de todo o sistema)
O aplicativo System manipula a grande maioria da interface com o usuário que basicamente consiste-se de diálogos como os avisos de volume, desbloqueio da senha do SIM e elementos de IU que afetam o comportamento da janela como o botão home por software.
z-index level
com o arquivo index.html
do aplicativo do sistema, muitos componentes são reuinidos com o atributo data-z-index-level
attribute, por examplo:
<div id="sleep-menu" data-z-index-level="sleep-menu"> ... </div>
Os z-index-levels
correspondentes são definidos dentro de system/style/zindex.css
, por exemplo:
#screen > [data-z-index-level="sleep-menu"] { z-index: 65536; } ... #screen > [data-z-index-level="app"] > .appWindow { z-index: 3; }
As configurações z-index são arranjadas de acordo com a ordem que os elementos são mostrados na tela — elementos que necessitam aparecer num nível maior da hierarquia recebem um número maior. Essa é a maneira que o aplicativo System lida com o gerenciamento das janelas num nível básico.
O botão home por software
O botão home por software é uma alternativa ao botão físico. É habilitado automaticamente em dispositivos que não possuem o botão físico, por exemplo o Nexus 4. Para controlar sua aparência o Gecko provê um recurso de mídia proprietário chamado-moz-physical-home-button
, que pode ser usado dentro de um "media query" para aplicar estilos baseados na presença de um botão home físico. O gerenciador de janelas reserva algum espaço na tela para o botão home se for solicitado.
No arquivo system/style/window.css
(e muitos outros arquivos de estilo do sistema), você pode ver isso:
@media not all and (-moz-physical-home-button) { #screen:not(.software-button-disabled) > #windows > .appWindow { bottom: 5rem; } }
Gesto do botão Home (deslizar para cima a partir da parte de baixo da tela)
O gesto do botão home é outra alternativa ao botão home físico, pode ser habilitado em configurações do desenvolvedor e o código que o controla pode ser encontrado em system/js/home_gesture.js
. O gesto consiste-se em deslizar o dedo de baixo para cima na tela e pode ser usado, por exemplo, para fechar os aplicativos:
O gesto será automaticamente habilitado nos tablets Firefox OS. The gesture will be automatically enabled on Firefox OS tablet devices. Os limites da tela definidos em gaia/shared/js/screen_layout.js
é usado para detectar se o dispositivo é um tablet ou não.
Diálogo de aviso do Volume
O código que controla o diálogo de aviso de volume pode ser encontrado em system/js/sound_manager.js
. Ele aparece quando ocorre algumas das situações:
- O fone de ouvido é conectado.
- O volume de 85dB é atingido.
- É executado um conteúdo no canal de audio.
Diálogo de desbloqueio de senha (PIN) do SIM
O código que controla esse diálogo está em system/js/simcard_dialog.js
— esse diálogo é apresentado quando a opção de bloqueio por senha está habilitada. É necessário ter permissões de telefonia descritas no arquivo manifest.webapp
(que o aplicativo System faz).
Nota: O diálogo de desbloqueio não aparece quando o telefone está em modo avião.