Google is committed to advancing racial equity for Black communities. See how.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

HIDL Java

O Android 8.0 reformulou o sistema operacional Android para definir interfaces claras entre a plataforma Android independente do dispositivo e o código específico do dispositivo e do fornecedor. O Android já definiu muitas dessas interfaces na forma de interfaces HAL, definidas como cabeçalhos C em hardware/libhardware . O HIDL substituiu essas interfaces HAL por interfaces estáveis ​​com versão, que podem ser em Java (descritas abaixo) ou como interfaces HIDL do lado do cliente e do servidor em C ++ .

As interfaces HIDL devem ser usadas principalmente a partir de código nativo e, como resultado, o HIDL se concentra na geração automática de código eficiente em C ++. No entanto, as interfaces HIDL também devem ser capazes de ser usadas diretamente do Java, pois alguns subsistemas Android (como telefonia) provavelmente terão interfaces HIDL Java.

As páginas nesta seção descrevem o front-end Java para interfaces HIDL, detalham como criar, registrar e usar serviços e explicam como HALs e clientes HAL escritos em Java interagem com o sistema HIDL RPC.

Ser um cliente

Este é um exemplo de um cliente para uma interface IFoo no pacote android.hardware.foo@1.0 que é registrado como nome de serviço default e um serviço adicional com o nome de serviço customizado second_impl .

Adicionar bibliotecas

Você precisa adicionar dependências na biblioteca stub HIDL correspondente se quiser usá-la. Normalmente, esta é uma biblioteca estática:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Se você sabe que já está puxando dependências dessas bibliotecas, também pode usar a vinculação compartilhada:

// in Android.bp
libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Considerações adicionais para adicionar bibliotecas no Android 10

Se você tiver um aplicativo de sistema / fornecedor direcionado ao Android 10 e superior, deverá incluir estaticamente essas bibliotecas. Para aplicativos mais antigos, o comportamento antigo é preservado. Como alternativa, é possível usar apenas classes HIDL de JARs personalizados instalados no dispositivo com APIs Java estáveis ​​disponibilizados usando o mecanismo de uses-library existente para aplicativos do sistema. Para economizar espaço em um dispositivo, esta é a abordagem recomendada. Para obter mais detalhes, consulte Implementando a biblioteca Java SDK .

A partir de 10, versões "superficiais" dessas bibliotecas também estão disponíveis. Isso inclui a classe em questão, mas não inclui nenhuma das classes dependentes. Por exemplo, android.hardware.foo-V1.0-java-shallow inclui classes no pacote foo, mas não inclui classes em android.hidl.base-V1.0-java , que contém a classe base de todos os HIDL interfaces. Se estiver criando uma biblioteca que já possui as classes base da interface preferencial disponíveis como uma dependência, você pode usar o seguinte:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java-shallow", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow

As bibliotecas de base e gerenciador HIDL também não estão mais disponíveis no classpath de inicialização. Em vez disso, eles foram movidos para um novo namespace com jarjar . Módulos no classpath de inicialização usando HIDL precisam usar as variantes superficiais dessas bibliotecas, bem como adicionar jarjar_rules: ":framework-jarjar-rules" ao seu Android.bp para evitar código duplicado e fazer com que aplicativos de sistema / fornecedor usem APIs ocultas .

Modificando sua fonte Java

Existe apenas uma versão ( @1.0 ) deste serviço, portanto, este código recupera apenas essa versão. Consulte as extensões de interface para saber como lidar com várias versões diferentes do serviço.

import android.hardware.foo.V1_0.IFoo;
...
// retry to wait until the service starts up if it is in the manifest
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IFoo anotherServer = IFoo.getService("second_impl", true /* retry */);
server.doSomething(…);

Prestando um serviço

O código da estrutura em Java pode precisar servir interfaces para receber callbacks assíncronos de HALs.

Para a interface IFooCallback na versão 1.0 do pacote android.hardware.foo , você pode implementar sua interface em Java usando as seguintes etapas:

  1. Defina sua interface em HIDL.
  2. Abra /tmp/android/hardware/foo/IFooCallback.java como uma referência.
  3. Crie um novo módulo para sua implementação Java.
  4. Examine a classe abstrata android.hardware.foo.V1_0.IFooCallback.Stub , em seguida, escreva uma nova classe para estendê-la e implementar os métodos abstratos.

Visualizando arquivos gerados automaticamente

Para visualizar os arquivos gerados automaticamente, execute:

hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0

Esses comandos geram o diretório /tmp/android/hardware/foo/1.0 . Para o arquivo hardware/interfaces/foo/1.0/IFooCallback.hal , isso gera o arquivo /tmp/android/hardware/foo/1.0/IFooCallback.java , que encapsula a interface Java, o código do proxy e os stubs (ambos proxy e os stubs estão em conformidade com a interface).

-Lmakefile gera as regras que executam este comando no momento da construção e permitem incluir android.hardware.foo-V1.0-java e vincular os arquivos apropriados. Um script que faz isso automaticamente para um projeto cheio de interfaces pode ser encontrado em hardware/interfaces/update-makefiles.sh . Os caminhos neste exemplo são relativos; hardware / interfaces podem ser um diretório temporário em sua árvore de código para permitir que você desenvolva um HAL antes de publicá-lo.

Executando um serviço

O HAL fornece a interface IFoo , que deve fazer retornos de chamada assíncronos para a estrutura por IFooCallback interface IFooCallback . A interface IFooCallback não é registrada por nome como um serviço detectável; em vez disso, IFoo deve conter um método como setFooCallback(IFooCallback x) .

Para configurar IFooCallback da versão 1.0 do pacote android.hardware.foo , adicione android.hardware.foo-V1.0-java ao Android.mk . O código para executar o serviço é:

import android.hardware.foo.V1_0.IFoo;
import android.hardware.foo.V1_0.IFooCallback.Stub;
....
class FooCallback extends IFooCallback.Stub {
    // implement methods
}
....
// Get the service you will be receiving callbacks from.
// This also starts the threadpool for your callback service.
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
....
// This must be a persistent instance variable, not local,
//   to avoid premature garbage collection.
FooCallback mFooCallback = new FooCallback();
....
// Do this once to create the callback service and tell the "foo-bar" service
server.setFooCallback(mFooCallback);

Extensões de interface

Supondo que um determinado serviço implemente a interface IFoo em todos os dispositivos, é possível que em um determinado dispositivo o serviço possa fornecer recursos adicionais implementados na extensão de interface IBetterFoo , como segue:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Chamar o código ciente da interface estendida pode usar o castFrom() Java para converter com segurança a interface base para a interface estendida:

IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IBetterFoo extendedService = IBetterFoo.castFrom(baseService);
if (extendedService != null) {
  // The service implements the extended interface.
} else {
  // The service implements only the base interface.
}