Rede e telefonia

Os recursos deste guia descrevem os recursos de gerenciamento de rede e telefonia que podem ser implementados no app controlador de política de dispositivo (DPC). Este documento contém exemplos de código, e você também pode usar o app Testar DPC como uma fonte de exemplo de código para recursos empresariais do Android.

Um app de DPC pode ser executado no modo de proprietário do perfil em dispositivos pessoais ou no modo de proprietário do dispositivo em dispositivos totalmente gerenciados. Esta tabela indica quais recursos estão disponíveis quando o DPC é executado no modo de proprietário do perfil ou do proprietário do dispositivo:

Recurso Proprietário do perfil Proprietário do dispositivo
Acesse contatos de trabalho em vários perfis
Garantir uma conexão de rede segura para o tráfego de trabalho
Configurar um único ID de rede sem fio entre regiões
Especificar um discador separado para o perfil de trabalho

Acessar contatos de trabalho em perfis

Os EMMs podem permitir que o perfil pessoal de um usuário acesse os contatos de trabalho para que os contatos pessoais e de trabalho sejam acessíveis pela pesquisa local e no diretório remoto. Em dispositivos pessoais, um único discador no perfil pessoal pode fazer e receber chamadas pessoais e de trabalho. Além disso, os contatos de trabalho são bem integrados à interface do sistema. Se o perfil de trabalho estiver criptografado, os dados dele não ficarão disponíveis para o perfil pessoal.

Integrado com a interface do sistema

A interface do sistema indica as chamadas de trabalho recebidas usando um ícone de maleta. O callLog também mostra o ícone para designar chamadas de trabalho recebidas e realizadas. O discador pessoal e os apps de contatos podem exibir as informações do identificador de chamadas de um contato de trabalho usando uma pesquisa de diretório remoto. Portanto, não é necessário que o contato já esteja sincronizado no dispositivo local. O app de mensagens pode fazer buscas e identificação de chamadas locais.

O Documento de definição de compatibilidade do Android (CDD) inclui requisitos para que os contatos de trabalho sejam exibidos no discador padrão e requisitos para que os contatos e os apps de mensagens tenham um selo para indicar que são do perfil de trabalho.

Os contatos de trabalho são acessíveis e pesquisáveis

O usuário pode acessar e chamar contatos de trabalho pelo perfil pessoal, que é exibido na tela de pesquisa do app discador. O usuário pode pesquisar contatos de trabalho usando o preenchimento automático, que são sincronizados localmente com o dispositivo e listados em uma pesquisa remota em um diretório.

Controlar contatos de trabalho no perfil principal

O DPC controla a permissão para pesquisar contatos de trabalho. Executado no modo de proprietário do perfil, o DPC gerencia a visibilidade dos contatos de trabalho no perfil pessoal. Para mais informações, consulte Criar um controlador de política de dispositivo.

A pesquisa de contatos de trabalho pelo perfil pessoal está ativada por padrão.

Garanta uma conexão de rede segura para o tráfego de trabalho

Em execução no modo de proprietário do dispositivo ou de proprietário do perfil, um controlador de política de dispositivo pode usar uma conexão de rede privada virtual (VPN) sempre ativada para forçar os aplicativos a transmitir tráfego por um app de VPN especificado que não pode ser ignorado. Usando uma conexão VPN sempre ativada, o DPC pode garantir que o tráfego de rede de um perfil de trabalho ou dispositivo gerenciado passe por um serviço de VPN e sem intervenção do usuário. Esse processo cria uma conexão de rede segura para o tráfego contínuo em um perfil de trabalho.

Sobre conexões VPN sempre ativadas

Como parte do framework do sistema, o roteamento de VPN é gerenciado automaticamente para que o usuário não possa ignorar o serviço de VPN. Se o serviço de VPN for desconectado enquanto o modo de bloqueio total for desconectado, o tráfego não poderá vazar para a Internet aberta. Para aplicativos que implementam o VpnService, a VPN sempre ativa oferece um framework para gerenciar e manter uma conexão VPN segura por meio de um servidor confiável. O serviço de VPN reinicia a conexão automaticamente entre as atualizações de apps, seja por Wi-Fi ou rede celular. Se o dispositivo for reinicializado, o framework reiniciará a conexão VPN.

A conexão com o serviço de VPN é transparente para o usuário. No caso de um dispositivo da empresa, o usuário não precisa confirmar uma caixa de diálogo de consentimento para uma VPN no modo sempre ativado. As configurações de rede VPN do usuário permitem ativar manualmente uma conexão sempre ativada.

Se DISALLOW_CONFIG_VPN for true, o usuário não poderá configurar a VPN. Ative o DISALLOW_DEBUGGING_FEATURES para impedir que os usuários substituam a VPN sempre ativada usando o comando adb debug. Para evitar que um usuário desinstale a VPN, chame DevicePolicyManager.setUninstallBlocked.

Configurar o serviço de VPN

A organização que usa sua solução empresarial para Android configura a VPN.

  1. Instale um app de VPN que implemente VpnService. É possível encontrar serviços de VPN ativos usando um filtro de intent que corresponda à ação VpnService.SERVICE_INTERFACE.
  2. Declare um VpnService no manifesto do app protegido pela permissão BIND_VPN_SERVICE.
  3. Configure o VpnService para que ele seja iniciado pelo sistema. Evite configurar o app de VPN para iniciar a si mesmo detectando uma inicialização do sistema e controlando o próprio ciclo de vida.
  4. Defina as configurações gerenciadas para o app de VPN. Confira o exemplo abaixo.

Ativar a conexão VPN sempre ativa

O DPC pode configurar uma conexão VPN sempre ativa por meio de um app específico chamando DevicePolicyManager.setAlwaysOnVpnPackage().

Essa conexão é concedida automaticamente e persiste após uma reinicialização. Se lockdownEnabled for falso, o tráfego de rede poderá ficar desprotegido no momento em que o smartphone for reinicializado e a VPN se conectar. Isso é útil se você não quiser interromper a conectividade de rede sempre que a VPN falhar ou se a VPN não for essencial.

Verificar a conexão VPN sempre ativa

O DPC pode ler o nome do pacote que administra uma conexão VPN sempre ativa para o usuário atual com DevicePolicyManager.getAlwaysOnVpnPackage()..

Se esse pacote não existir ou se a VPN tiver sido criada no app Configurações do sistema, null será retornado.

Exemplo

No app TestDPC, o AlwaysOnVpnFragment.java usa essas APIs para ativar a configuração de uma conexão VPN sempre ativa.

No exemplo a seguir:

  • As configurações gerenciadas do serviço de VPN são definidas pelo DevicePolicyManager usando o método setApplicationRestrictions().
  • As configurações gerenciadas usam pares de chave-valor arbitrários, e este app de exemplo os usa em outro lugar para definir as configurações de rede da VPN. Consulte Verificar configurações gerenciadas.
  • O exemplo adiciona o instalador do pacote do Android a uma lista de bloqueio para não atualizar os pacotes do sistema pela VPN. Todo o tráfego de rede do usuário no perfil de trabalho ou dispositivo passa por esse app de VPN, exceto o instalador do pacote. As atualizações usam a Internet aberta.
  • O DevicePolicyManager ativa a conexão VPN sempre ativa para o pacote VPN usando setAlwaysOnVpnPackage() e ativando o modo de bloqueio total.

Kotlin

// Set VPN's managed configurations
val config = Bundle().apply {
  putString(Extras.VpnApp.ADDRESS, "192.0.2.0")
  putString(Extras.VpnApp.IDENTITY, "vpn.account1")
  putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate")
  putStringArray(Extras.VpnApp.DENYLIST,
        arrayOf("com.android.packageinstaller"))
}

val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

val admin = myDeviceAdminReceiver.getComponentName(this)

// Name of package to update managed configurations
val vpnPackageName = "com.example.vpnservice"

// Associate managed configurations with DeviceAdminReceiver
dpm.setApplicationRestrictions(admin, vpnPackageName, config)

// Enable always-on VPN connection through VPN package
try {
  val lockdownEnabled = true
  dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled)
} catch (ex: Exception) {
  throw PolicyException()
}

Java

// Set VPN's managed configurations
final Bundle config = new Bundle();
config.putString(Extras.VpnApp.ADDRESS, "192.0.2.0");
config.putString(Extras.VpnApp.IDENTITY, "vpn.account1");
config.putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate");
config.putStringArray(Extras.VpnApp.DENYLIST,
                      new String[]{"com.android.packageinstaller"});

DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);

ComponentName admin = myDeviceAdminReceiver.getComponentName(this);

// Name of package to update managed configurations
final String vpnPackageName = "com.example.vpnservice";

// Associate managed configurations with DeviceAdminReceiver
dpm.setApplicationRestrictions(admin, vpnPackageName, config);

// Enable always-on VPN connection through VPN package
try {
  boolean lockdownEnabled = true;
  dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled));
} catch (Exception ex) {
  throw new PolicyException(...);
}

Configurar um único ID de rede sem fio entre regiões

Em execução no modo de proprietário do dispositivo ou de proprietário do perfil, um controlador de política de dispositivo (DPC, na sigla em inglês) pode associar vários certificados de autoridade de certificação (CA, na sigla em inglês) a uma única configuração de rede sem fio. Com essa configuração, um dispositivo pode se conectar a pontos de acesso sem fio que têm o mesmo nome de rede ou identificador de conjunto de serviços (SSID), mas estão configurados com diferentes certificados de CA. Isso é útil quando as redes sem fio da sua organização estão localizadas em várias regiões geográficas e cada região exige uma autoridade de certificação diferente. Por exemplo, assinaturas legais podem exigir uma autoridade local que precisa de uma CA regional.

Observação:o Android oferece suporte a setCaCertificate desde a API 18 (Jelly Bean), mas os administradores de TI precisam provisionar as redes separadamente com cada CA para garantir que os dispositivos tenham autenticação integrada em cada ponto de acesso, independentemente da região.

Especificar certificados de CA para identificar o servidor

Para especificar uma lista de certificados X.509 que identificam o servidor usando o mesmo SSID, inclua todas as CAs relevantes na configuração sem fio usando WifiEnterpriseConfig.setCaCertificates().

O certificado de um servidor será válido se a CA corresponder a um dos certificados fornecidos. Os nomes padrão são atribuídos automaticamente aos certificados e usados na configuração. O WifiManager instala o certificado, salva a configuração automaticamente quando a rede está ativada e remove o certificado quando a configuração é excluída.

Para receber todos os certificados de CA associados à configuração sem fio, use WifiEnterpriseConfig.getCaCertificates() para retornar uma lista de objetos X509Certificate.

Adicionar uma configuração sem fio usando vários certificados de CA

  1. Verifique a identidade do servidor:
    1. Carregue os certificados de CA X.509.
    2. Carregar a chave privada e o certificado do cliente. Consulte Segurança com HTTPS e SSL para ver um exemplo de como ler um arquivo de certificado.
  2. Crie um novo WifiConfiguration e defina o SSID (Identificador do conjunto de serviços) e o gerenciamento de chaves dele.
  3. Configure a instância WifiEnterpriseConfig no WifiConfiguration.
    1. Identifique o servidor com uma lista de objetos X509Certificate usando setCaCertificates().
    2. Defina as credenciais, a identidade e a senha do cliente.
    3. Defina o método de protocolo de autenticação extensível (EAP, na sigla em inglês) e o método da Fase 2 como parte do estabelecimento da conexão.
  4. Adicione a rede com o WifiManager.
  5. Ative a rede. O WifiManager salva a configuração automaticamente durante a configuração.

Este exemplo une as etapas:

Kotlin

// Verify the server's identity
val caCert0 = getCaCert("cert0.crt")
val caCert1 = getCaCert("cert1.crt")
val clientKey = getClientKey()
val clientCert = getClientCert()

// Create Wi-Fi configuration
val wifiConfig = WifiConfiguration().apply {
  SSID = "mynetwork"
  allowedKeyManagement.set(KeyMgmt.WPA_EAP)
  allowedKeyManagement.set(KeyMgmt.IEEE8021X)

  // Set up Wi-Fi enterprise configuration
  enterpriseConfig.setCaCertificates(arrayOf<X509Certificate>(caCert0, caCert1))
  enterpriseConfig.setClientKeyEntry(clientKey, clientCert)
  enterpriseConfig.setIdentity("myusername")
  enterpriseConfig.setEapMethod(Eap.TLS)
  enterpriseConfig.setPhase2Method(Phase2.NONE)
}


// Add network
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
val netId = wifiManager.addNetwork(wifiConfig)

// Enable network
if (netId < 0) {
  // Error creating new network
} else {
  wifiManager.enableNetwork(netId, true)
}

Java

// Verify the server's identity
X509Certificate caCert0 = getCaCert("cert0.crt");
X509Certificate caCert1 = getCaCert("cert1.crt");
PrivateKey clientKey = getClientKey();
X509Certificate clientCert = getClientCert();

// Create Wi-Fi configuration
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = "mynetwork";
wifiConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
wifiConfig.allowedKeyManagement.set(KeyMgmt.IEEE8021X);

// Set up Wi-Fi enterprise configuration
wifiConfig.enterpriseConfig.setCaCertificates(new X509Certificate[] {caCert0, caCert1});
wifiConfig.enterpriseConfig.setClientKeyEntry(clientKey, clientCert);
wifiConfig.enterpriseConfig.setIdentity("myusername");
wifiConfig.enterpriseConfig.setEapMethod(Eap.TLS);
wifiConfig.enterpriseConfig.setPhase2Method(Phase2.NONE);

// Add network
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
int netId = wifiManager.addNetwork(wifiConfig);

// Enable network
if (netId < 0) {
  // Error creating new network
} else {
  wifiManager.enableNetwork(netId, true);
}

Especificar um discador separado para o perfil de trabalho

Você pode colocar um aplicativo discador separado na lista de permissões para usar em um perfil de trabalho. Pode ser o próprio discador ou um app de voz sobre IP (VoIP, na sigla em inglês) que implementa a API ConnectionService para o back-end de chamada. Isso fornece a mesma experiência de discagem da interface do sistema integrada para aplicativos VoIP no perfil de trabalho, tornando o discador de trabalho um recurso principal. As chamadas recebidas para as contas de trabalho são diferenciadas das chamadas recebidas para as contas pessoais.

O usuário pode optar por fazer e receber chamadas do discador de trabalho permitido em uma conta telefônica. Todas as chamadas feitas desse discador ou recebidas para a conta de telefone de trabalho são gravadas no provedor CallLog do perfil de trabalho. O discador de trabalho mantém um registro de chamadas exclusivo com acesso apenas aos contatos de trabalho. As chamadas de switch de circuito recebidas são processadas pelo discador principal e armazenadas em um registro de chamadas pessoal. Se um perfil de trabalho for excluído, o registro de chamadas associado a ele também será excluído, assim como todos os dados dele.

Os apps de terceiros precisam implementar ConnectionService

Os apps VoIP de terceiros que precisam fazer chamadas telefônicas e essas chamadas integradas ao app de telefone integrado podem implementar a API ConnectionService. Obrigatório para qualquer serviço VoIP usado para chamadas de trabalho. Esses apps se beneficiam porque as chamadas são tratadas como chamadas de celular tradicionais. Por exemplo, elas aparecem no discador integrado do sistema e no registro de chamadas. Se o app que está implementando ConnectionService estiver instalado no perfil de trabalho, ele só poderá ser acessado por um discador também instalado nesse perfil de trabalho.

Depois que o desenvolvedor implementar o ConnectionService, ele precisará adicioná-lo ao arquivo de manifesto do app e registrar um PhoneAccount com o TelecomManager. Uma conta telefônica representa um método distinto para fazer ou receber chamadas, e pode haver vários PhoneAccounts para cada ConnectionService. Depois que a conta telefônica é registrada, o usuário pode ativá-la nas configurações do discador.

Integração e notificações da interface do sistema

A interface do sistema oferece aos usuários uma experiência de discagem consistente e integrada para apps de terceiros que usam a API ConnectionService como back-end para fazer chamadas. Se você estiver usando o app em um perfil de trabalho, um ícone de pasta será exibido nas chamadas recebidas e na barra de status. Um app que implementa o ConnectionService instalado no perfil de trabalho pode usar o discador do sistema ou criar um discador de trabalho separado. Eles podem ser um único app ou separados.

O aplicativo de telefone determina se está fazendo ou recebendo uma chamada de trabalho verificando a flag android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL. Se for uma chamada de trabalho, o discador indica isso ao usuário adicionando um selo de trabalho (o ícone de pasta):

Kotlin

// Call placed through a work phone account. getCurrentCall() is defined by the
// dialer.
val call = getCurrentCall()
if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) {
  // Set briefcase icon
}

Java

// Call placed through a work phone account. getCurrentCall() is defined by the
// dialer.
Call call = getCurrentCall();
if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) {
  // Set briefcase icon
}