Réseau et téléphonie

Les fonctionnalités présentées dans ce guide décrivent les fonctionnalités de gestion de réseau et de téléphonie que vous pouvez implémenter dans votre application de contrôleur des règles relatives aux appareils (DPC). Ce document contient des exemples de code et vous pouvez également utiliser l'application Test DPC comme source d'exemple de code pour les fonctionnalités d'entreprise d'Android.

Une application DPC peut s'exécuter en mode propriétaire de profil sur des appareils personnels ou en mode propriétaire de l'appareil sur des appareils entièrement gérés. Ce tableau indique les fonctionnalités disponibles lorsque le DPC s'exécute en mode propriétaire de profil ou propriétaire d'appareil:

Fonctionnalité Propriétaire du profil Propriétaire de l'appareil
Accéder aux contacts professionnels sur tous les profils
Assurez-vous d'une connexion réseau sécurisée pour le trafic professionnel
Configurer un seul ID de réseau sans fil pour toutes les régions
Spécifiez un clavier distinct pour le profil professionnel

Accéder aux contacts professionnels dans tous les profils

Les EMM peuvent autoriser le profil personnel d'un utilisateur à accéder à ses contacts professionnels, afin que ceux-ci soient accessibles via la recherche locale et la recherche dans l'annuaire à distance. Sur les appareils personnels, un clavier unique dans le profil personnel peut passer et recevoir des appels personnels et professionnels. De plus, les contacts professionnels sont bien intégrés à l'interface utilisateur du système. S'il est chiffré, le profil personnel n'a pas accès à ses données.

Intégré à l'UI du système

L'UI du système indique les appels professionnels entrants à l'aide d'une icône en forme de mallette. Le callLog affiche également l'icône permettant de désigner les appels professionnels entrants et sortants. Les applications de numérotation personnelle et de contact peuvent afficher le numéro d'appelant d'un contact professionnel à l'aide d'une recherche à distance dans l'annuaire. Il n'est donc pas nécessaire que le contact soit déjà synchronisé sur l'appareil local. L'application de chat vous permet d'identifier l'appelant local et d'effectuer des recherches.

Le document de définition de compatibilité Android (CDD, Compatibility Definition Document) Android requiert l'affichage des contacts professionnels dans le clavier par défaut, ainsi que l'affichage d'un badge pour les contacts et les applications de chat, indiquant qu'ils proviennent du profil professionnel.

Les contacts professionnels sont accessibles et inclus dans l'index de recherche

L'utilisateur peut accéder aux contacts professionnels et les appeler à partir de son profil personnel, qui s'affiche dans l'écran de recherche de l'application Téléphone. L'utilisateur peut rechercher des contacts professionnels à l'aide de la saisie semi-automatique qui sont synchronisés localement avec l'appareil et répertoriés via une recherche à distance dans l'annuaire.

Contrôler les contacts professionnels dans le profil principal

Le DPC contrôle l'autorisation de rechercher des contacts professionnels. S'exécutant en mode propriétaire de profil, le DPC gère la visibilité des contacts professionnels dans le profil personnel. Pour en savoir plus, consultez la section Créer un outil de contrôle des règles relatives aux appareils.

La recherche de contacts professionnels par profil personnel est activée par défaut.

Garantir une connexion réseau sécurisée pour le trafic professionnel

Exécution en mode propriétaire de l'appareil ou en mode propriétaire de profil, un outil de contrôle des règles relatives aux appareils peut utiliser une connexion VPN (réseau privé virtuel) toujours activée pour forcer les applications à transmettre le trafic via une application VPN spécifiée qui ne peut pas être contournée. Grâce à une connexion VPN permanente, le DPC peut garantir que le trafic réseau d'un profil professionnel ou d'un appareil géré passe par un service VPN, sans intervention de l'utilisateur. Ce processus crée une connexion réseau sécurisée pour permettre un trafic continu dans un profil professionnel.

À propos des connexions VPN permanentes

Dans le framework système, le routage VPN est automatiquement géré afin que l'utilisateur ne puisse pas contourner le service VPN. Si le service VPN est déconnecté en mode verrouillé, le trafic ne peut pas fuir vers l'Internet ouvert. Pour les applications mettant en œuvre VpnService, le VPN permanent fournit un framework permettant de gérer et de maintenir une connexion VPN sécurisée via un serveur de confiance. Le service VPN redémarre automatiquement la connexion lors des mises à jour de l'application, qu'elle soit effectuée via le Wi-Fi ou un réseau mobile. Si l'appareil redémarre, le framework redémarre la connexion VPN.

La connexion au service VPN est transparente pour l'utilisateur. Pour un appareil détenu par l'entreprise, l'utilisateur n'est pas tenu de confirmer la boîte de dialogue de recueil du consentement pour un VPN en mode Always-on. Les paramètres réseau VPN de l'utilisateur permettent d'activer manuellement une connexion permanente.

Si DISALLOW_CONFIG_VPN est défini sur true, l'utilisateur ne peut pas configurer le VPN. Activez DISALLOW_DEBUGGING_FEATURES pour empêcher les utilisateurs de remplacer le VPN permanent à l'aide de la commande de débogage adb. Pour empêcher un utilisateur de désinstaller le VPN, appelez DevicePolicyManager.setUninstallBlocked.

Configurer le service VPN

L'organisation qui utilise votre solution d'entreprise pour Android configure un VPN.

  1. Installez une application VPN qui implémente VpnService. Vous pouvez trouver des services VPN actifs en utilisant un filtre d'intent correspondant à l'action VpnService.SERVICE_INTERFACE.
  2. Déclarez un VpnService dans le fichier manifeste de l'application protégé par l'autorisation BIND_VPN_SERVICE.
  3. Configurez le VpnService pour qu'il soit lancé par le système. Évitez de configurer l'application VPN pour qu'elle démarre automatiquement en écoutant le démarrage du système et en contrôlant son propre cycle de vie.
  4. Définissez les configurations gérées pour l'application VPN (voir l'exemple ci-dessous).

Activer la connexion VPN permanente

Le DPC peut configurer une connexion VPN permanente via une application spécifique en appelant DevicePolicyManager.setAlwaysOnVpnPackage().

Cette connexion est automatiquement accordée et persiste après un redémarrage. Si lockdownEnabled est défini sur "false", le trafic réseau peut être non sécurisé à partir du redémarrage du téléphone et de la connexion du VPN. Cela est utile si vous ne souhaitez pas interrompre la connectivité réseau en cas de défaillance du VPN ou si le VPN n'est pas essentiel.

Vérifier la connexion au VPN permanent

Le DPC peut lire le nom du package qui administre une connexion VPN permanente pour l'utilisateur actuel avec DevicePolicyManager.getAlwaysOnVpnPackage()..

En l'absence de package de ce type ou si le VPN a été créé dans l'application Paramètres du système, null est renvoyé.

Exemple

Dans l'application TestDPC, AlwaysOnVpnFragment.java utilise ces API pour activer le paramètre d'une connexion VPN permanente.

Dans l'exemple ci-dessous :

  • Les configurations gérées du service VPN sont définies par DevicePolicyManager à l'aide de sa méthode setApplicationRestrictions().
  • Les configurations gérées utilisent des paires clé/valeur arbitraires, qui sont utilisées dans cet exemple d'application ailleurs pour configurer les paramètres réseau du VPN (voir Vérifier les configurations gérées).
  • L'exemple ajoute le programme d'installation du package Android à une liste de blocage afin de ne pas mettre à jour les packages système sur le VPN. Tout le trafic réseau de l'utilisateur dans le profil professionnel ou l'appareil passe par cette application VPN, à l'exception du programme d'installation du package ; ses mises à jour utilisent l'Internet ouvert.
  • DevicePolicyManager active ensuite la connexion VPN permanente pour le package VPN à l'aide de setAlwaysOnVpnPackage(), ce qui active le mode de blocage.

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(...);
}

Configurer un seul ID de réseau sans fil pour toutes les régions

Exécution en mode propriétaire de l'appareil ou en mode propriétaire de profil, un outil de contrôle des règles relatives aux appareils (DPC) peut associer plusieurs certificats d'autorité de certification à une seule configuration de réseau sans fil. Avec cette configuration, un appareil peut se connecter à des points d'accès sans fil ayant le même nom de réseau ou le même identifiant d'ensemble de services (SSID), mais qui sont configurés avec des certificats CA différents. Cela est utile si les réseaux sans fil de votre organisation sont situés dans plusieurs régions géographiques et que chaque région nécessite une autorité de certification différente. Par exemple, les signatures légales peuvent nécessiter une autorité locale ayant besoin d'une autorité de certification régionale.

Remarque:Android est compatible avec setCaCertificate depuis l'API 18 (Jelly Bean), mais les administrateurs informatiques doivent provisionner leurs réseaux séparément avec chaque autorité de certification pour que les appareils s'authentifient facilement à chaque point d'accès, quelle que soit leur région.

Spécifier des certificats CA pour identifier le serveur

Pour spécifier une liste de certificats X.509 identifiant le serveur avec le même SSID, incluez toutes les autorités de certification pertinentes dans la configuration sans fil à l'aide de WifiEnterpriseConfig.setCaCertificates().

Le certificat d'un serveur est valide si son autorité de certification correspond à l'un des certificats donnés. Les noms par défaut sont automatiquement attribués aux certificats et utilisés dans la configuration. Le WifiManager installe le certificat et enregistre automatiquement la configuration lorsque le réseau est activé, puis le supprime lorsque la configuration est supprimée.

Pour obtenir tous les certificats CA associés à la configuration sans fil, utilisez WifiEnterpriseConfig.getCaCertificates() afin de renvoyer une liste d'objets X509Certificate.

Ajouter une configuration sans fil à l'aide de plusieurs certificats CA

  1. Vérifiez l'identité du serveur :
    1. Chargez les certificats CA X.509.
    2. Chargez la clé privée et le certificat du client. Voir Sécurité avec HTTPS et SSL pour obtenir un exemple de lecture d'un fichier de certificat.
  2. Créez un WifiConfiguration, puis définissez son SSID et sa gestion de clé.
  3. Configurez l'instance WifiEnterpriseConfig sur ce WifiConfiguration.
    1. Identifiez le serveur avec une liste d'objets X509Certificate à l'aide de setCaCertificates().
    2. Définissez les identifiants, l'identité et le mot de passe du client.
    3. Définissez le protocole EAP (Extensible Authentication Protocol) et la méthode de phase 2 dans le cadre de l'établissement de la connexion.
  4. Ajoutez le réseau avec le WifiManager.
  5. Activez le réseau. WifiManager enregistre automatiquement la configuration lors de l'installation.

Cet exemple relie les étapes entre elles:

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);
}

Indiquer un clavier distinct pour le profil professionnel

Vous pouvez ajouter une application de téléphonie distincte à la liste d'autorisation à utiliser dans un profil professionnel. Il peut s'agir du clavier lui-même ou d'une application VoIP (Voice over IP) qui implémente l'API ConnectionService pour le backend appelant. Cette solution offre la même expérience intégrée de numérotation de l'UI du système pour les applications VoIP dans le profil professionnel, faisant de la numérotation professionnelle une fonctionnalité essentielle. Les appels entrants vers les comptes d'appels professionnels sont différents des appels entrants vers les comptes d'appels personnels.

L'utilisateur peut choisir de passer et recevoir des appels sur un compte téléphonique à partir du clavier professionnel figurant sur la liste d'autorisation. Tous les appels effectués à partir de ce clavier ou entrants sur le compte téléphonique professionnel sont enregistrés dans le fournisseur CallLog du profil professionnel. Le clavier professionnel gère un journal d'appels professionnel uniquement avec un accès aux contacts professionnels. Les appels entrants de commutateurs de circuit sont gérés par le clavier principal et stockés dans un journal d'appels personnel. Si un profil professionnel est supprimé, le journal d'appels associé à ce profil professionnel est également supprimé, ainsi que toutes les données de ce profil.

Les applications tierces doivent implémenter ConnectionService

Les applications VoIP tierces qui doivent passer des appels téléphoniques et dont ces appels sont intégrés dans l'application téléphonique intégrée peuvent implémenter l'API ConnectionService. Cette étape est obligatoire pour tous les services VoIP utilisés pour les appels professionnels. Ces applications présentent l'avantage de traiter les appels comme des appels cellulaires traditionnels. Par exemple, elles apparaissent dans le clavier système intégré et dans le journal d'appels. Si l'application qui implémente ConnectionService est installée dans le profil professionnel, elle n'est accessible que par un clavier également installé dans ce profil professionnel.

Une fois que le développeur a implémenté ConnectionService, il doit l'ajouter au fichier manifeste de l'application et enregistrer un PhoneAccount avec TelecomManager. Un compte téléphonique représente une méthode distincte pour passer ou recevoir des appels téléphoniques. Il peut y avoir plusieurs PhoneAccounts pour chaque ConnectionService. Une fois le compte de téléphone enregistré, l'utilisateur peut l'activer via les paramètres du clavier.

Intégration de l'UI du système et notifications

L'UI du système offre aux utilisateurs une expérience de numérotation cohérente et intégrée pour les applications tierces qui utilisent l'API ConnectionService comme backend pour passer des appels. Si vous utilisez l'application dans un profil professionnel, une icône en forme de mallette s'affiche lors des appels entrants et dans la barre d'état. Une application qui implémente ConnectionService installé dans le profil professionnel peut utiliser le clavier système ou créer un clavier professionnel distinct. Il peut s'agir d'une application unique ou d'applications distinctes.

L'application téléphonique détermine si elle passe ou reçoit un appel professionnel en recherchant l'indicateur android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL. S'il s'agit d'un appel professionnel, le clavier l'indique à l'utilisateur en ajoutant un badge professionnel (icône en forme de mallette):

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
}