Por dentro de pacotes OTA

O sistema cria o binário do atualizador de bootable/recovery/updater e o usa em um pacote OTA.

O pacote em si é um arquivo ZIP (ota_update.zip, incremental_ota_update.zip) que contém o binário executável META-INF/com/google/android/update-binary

O atualizador contém várias funções integradas e um intérprete para um scripting extensível (edify) compatível com comandos para tarefas típicas relacionadas a atualizações. Aparências do atualizador no arquivo .zip do pacote para um script no arquivo META-INF/com/google/android/updater-script:

Observação:não é comum usar o script e/ou as funções integradas do edify atividade, mas pode ser útil se você precisar depurar o arquivo de atualização.

Sintaxe de Edify

Um script do Google edify é uma expressão única em que todos os valores são strings. Strings vazias são false em um contexto booleano e todas as outras strings são true. O Edify oferece suporte à seguintes operadores (com os significados comuns):

(expr )
 expr + expr  # string concatenation, not integer addition
 expr == expr
 expr != expr
 expr && expr
 expr || expr
 ! expr
 if expr then expr endif
 if expr then expr else expr endif
 function_name(expr, expr,...)
 expr; expr

Qualquer string dos caracteres a-z, A-Z, 0-9, _, :, /, . que não seja uma palavra reservada é considerado um literal de string. As palavras reservadas são if else e depois endif.. Corda os literais também podem aparecer entre aspas duplas. como criar valores com espaços em branco e outros caracteres que não estejam no conjunto acima. \n, \t, \" e \\ como escapes entre aspas como \x##.

O && e || operadores estão em curto-circuito. o lado direito não é avaliado se o resultado lógico é determinado pelo lado esquerdo. Os seguintes são equivalentes:

e1 && e2
if e1 then e2 endif

O ; O operador é um ponto de sequência. significa avaliar primeiro o lado esquerdo e depois o lado direito. Seu valor é o valor da expressão do lado direito. Um ponto e vírgula também pode aparecer após uma expressão, de modo que o efeito simula instruções em estilo C:

prepare();
do_other_thing("argument");
finish_up();

Funções integradas

A maioria das funcionalidades de atualização está nas funções disponíveis para execução por scripts. Estritamente falando, são macros em vez de funções no sentido da Lisp. já que eles não precisam avaliar todos os argumentos.) Salvo indicação em contrário, as funções retornam true em caso de sucesso e false em caso de erro. Se você quiser que os erros cancelem a execução da use as funções abort() e/ou assert(). O conjunto de as funções disponíveis no Updater também podem ser estendidas para fornecer funcionalidades específicas do dispositivo.

abort([msg])
Cancela a execução do script imediatamente com a msg opcional. Se o usuário tiver estiver ativada, a mensagem msg aparecerá no registro de recuperação e na tela.
assert(expr[, expr, ...])
Avalia cada expr, por vez. Se algum for falso, aborta imediatamente a execução com o mensagem "falha na declaração" e o texto de origem da expressão com falha.
apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...])
Aplica um patch binário ao src_file para produzir o tgt_file. Se o o destino desejado for igual à origem, transmita "-" para tgt_file . tgt_sha1 e tgt_size é o hash SHA1 final esperado e o tamanho do arquivo de destino. Os valores restantes devem vir em pares: um hash SHA1 (uma string hexadecimal de 40 caracteres) e um blob. O blob é o patch a ser aplicado quando o conteúdo atual do arquivo de origem tiver o SHA1 especificado.

A aplicação de patches é feita de maneira segura, garantindo que o arquivo de destino tenha o hash SHA1 desejado e o tamanho desejado ou se está intocado, não será mantido em uma versão irrecuperável estado intermediário. Se o processo for interrompido durante a aplicação de patches, o arquivo de destino em um estado intermediário; há uma cópia na partição de cache. Portanto, reiniciar a atualização possam atualizar o arquivo.

Há suporte para sintaxe especial para tratar o conteúdo do dispositivo de tecnologia de memória (MTD, na sigla em inglês) partições diferentes como arquivos, permitindo a correção de partições brutas, como inicialização. Para ler um MTD partição, você precisa saber quantos dados quer ler, já que ela não tem uma ideia de fim de arquivo. Você pode usar a string "MTD:partition:size_1:sha1_1:size_2:sha1_2" como nome do arquivo para ler a partição especificada. É necessário especificar pelo menos um (size, sha-1) par; é possível especificar mais de um se houver vários possibilidades para o que você espera ler.

apply_patch_check(filename, sha1[, sha1, ...])
Retorna "true" se o conteúdo de filename ou a cópia temporária na partição de cache (se presente) têm uma soma de verificação SHA1 igual a um dos valores sha1 fornecidos. Os valores sha1 são especificados como 40 dígitos hexadecimais. Essa função é diferente da sha1_check(read_file(filename), sha1 [, ...]) porque ele sabe verifica a cópia da partição de cache, portanto, apply_patch_check() terá êxito mesmo se o arquivo foi corrompido por um apply_patch() update interrompido.
apply_patch_space(bytes)
Retorna "true" se pelo menos bytes de espaço de rascunho estiverem disponíveis para aplicar o binário manchas.
concat(expr[, expr, ...])
Avalia cada expressão e as concatena. O operador + é uma sintaxe sintática no caso especial de dois argumentos (mas a forma da função pode assumir qualquer número de ou expressões idiomáticas). As expressões precisam ser strings. não é possível concatenar blobs.
file_getprop(filename, key)
Lê o nome de arquivo fornecido e o interpreta como um arquivo de propriedades (por exemplo, /system/build.prop) e retorna o valor da key especificada ou a uma string vazia se key não estiver presente.
format(fs_type, partition_type, location, fs_size, mount_point)
Reformata uma partição especificada. Tipos de partição compatíveis:
  • fs_type="yaffs2" e particiona_type="MTD". O local precisa ser o nome do MTD partição; um sistema de arquivos yaffs2 vazio é construído lá. Os argumentos restantes são o que não é usado.
  • fs_type="ext4" epartition_type="EMMC". O local deve ser o arquivo do dispositivo do partição. Um sistema de arquivos ext4 vazio é construído lá. Se fs_size for zero, o do sistema ocupa toda a partição. Se fs_size for um número positivo, o do sistema de arquivos recebe os primeiros bytes fs_size da partição. Se fs_size for um número negativo, o sistema de arquivos vai pegar todos, exceto os últimos |fs_size| bytes do partição.
  • fs_type="f2fs" epartition_type="EMMC". O local deve ser o arquivo do dispositivo do partição. fs_size precisa ser um número não negativo. Se fs_size for zero, o do sistema ocupa toda a partição. Se fs_size for um número positivo, o do sistema de arquivos recebe os primeiros bytes fs_size da partição.
  • mount_point precisa ser o futuro ponto de montagem do sistema de arquivos.
getprop(key)
Retorna o valor da propriedade key do sistema (ou a string vazia, se não estiver definida). Os valores de propriedade do sistema definidos pela partição de recuperação não são necessariamente os mesmos que do sistema principal. Essa função retorna o valor na recuperação.
greater_than_int(a, b)
Retorna verdadeiro somente se (iff) a (interpretado como um número inteiro) for maior que b (interpretado como um número inteiro).
ifelse(cond, e1[, e2])
Avalia cond. Se for verdadeiro, avalia e retorna o valor de e1. Caso contrário, ele avalia e retorna e2 (se presente). A cláusula "if ... else ... then ... ” construto é apenas uma facilidade sintática para esta função.
is_mounted(mount_point)
Retorna verdadeiro se houver um sistema de arquivos montado em mount_point.
is_substring(needle, haystack)
Retorna verdadeiro iff needle é uma substring de haystack.
less_than_int(a, b)
Retorna verdadeiro se a (interpretado como um número inteiro) for menor que b (interpretado como um número inteiro).
mount(fs_type, partition_type, name, mount_point)
Monta um sistema de arquivos de fs_type em mount_point. partition_type precisa ser uma destas:
  • MTD (em inglês). Nome é o nome de uma partição MTD (por exemplo, system, userdata; consulte /proc/mtd no dispositivo para uma lista completa).
  • EMMC.

Por padrão, a recuperação não monta nenhum sistema de arquivos (exceto o cartão SD, se o usuário fazer uma instalação manual de um pacote a partir do cartão SD); seu script precisa montar as partições que precisa modificar.

package_extract_dir(package_dir, dest_dir)
Extrai todos os arquivos do pacote abaixo de package_dir e os grava no árvore correspondente abaixo de dest_dir. Todos os arquivos atuais serão substituídos.
package_extract_file(package_file[, dest_file])
Extrai um único package_file do pacote de atualização e o grava em dest_file, substituindo os arquivos existentes, se necessário. Sem o dest_file, que retorna o conteúdo do arquivo de pacote como um blob binário.
read_file(filename)
Lê o filename e retorna o conteúdo dele como um blob binário.
run_program(path[, arg, ...])
Executa o binário em path, transmitindo args. Retorna o status de saída do programa.
set_progress(frac)
Define a posição do medidor de progresso dentro do bloco definido pelo show_progress(). frac precisa estar no intervalo [0,0, 1,0]. O progresso o medidor nunca se move para trás; tentativas de fazer isso serão ignoradas.
sha1_check(blob[, sha1])
O argumento blob é um blob do tipo retornado por read_file() ou pelo forma de um argumento de package_extract_file() . Sem argumentos sha1, esta função retorna o hash SHA1 do blob (como uma string hexadecimal de 40 dígitos). Com um ou mais sha1, essa função retornará o hash SHA1 se ele for igual a um dos argumentos ou a string vazia se não for igual a nenhum deles.
show_progress(frac, secs)
avança o medidor de progresso até a próxima fra do comprimento dele. secs segundos (precisa ser um número inteiro). secs pode ser 0. Nesse caso, o medidor é não são avançados automaticamente, mas pelo uso da função set_progress() definida acima.
sleep(secs)
Suspende por secs segundos (precisa ser um número inteiro).
stdout(expr[, expr, ...])
Avalia cada expressão e despeja o valor dela em stdout. Útil para depuração.
tune2fs(device[, arg, …])
Ajusta os parâmetros ajustáveis args no device.
ui_print([text, ...])
Concatena todos os argumentos de texto e exibe o resultado na IU (onde será visível se o usuário tiver ativado a exibição de texto).
unmount(mount_point)
Desmonta o sistema de arquivos montado em mount_point.
wipe_block_device(block_dev, len)
Apaga os bytes len do dispositivo de bloco block_dev especificado.
wipe_cache()
Faz com que a partição de cache seja apagada no final de uma instalação bem-sucedida.
write_raw_image(filename_or_blob, partition)
Grava a imagem em filename_or_blob na partition do MTD. filename_or_blob pode ser uma string que nomeia um arquivo local ou um argumento com valor blob que contêm os dados a serem gravados. Para copiar um arquivo do pacote OTA para uma partição, use: write_raw_image(package_extract_file("zip_filename"), "partition_name");

Observação:antes do Android 4.1, apenas nomes de arquivos eram aceitos. Portanto, os dados primeiro tiveram que ser descompactados em um arquivo local temporário.