Сеть и телефония

Функции в этом руководстве описывают возможности управления сетью и телефонией, которые вы можете реализовать в приложении контроллера политики устройств (DPC). Этот документ содержит примеры кода, и вы также можете использовать приложение Test DPC в качестве источника примера кода для корпоративных функций Android.

Приложение DPC может работать в режиме владельца профиля на персональных устройствах или в режиме владельца устройства на полностью управляемых устройствах. В этой таблице указано, какие функции доступны, когда ЦОД работает в режиме владельца профиля или в режиме владельца устройства :

Особенность Владелец профиля Владелец устройства
Доступ к рабочим контактам в профилях
Обеспечьте безопасное сетевое соединение для рабочего трафика.
Настройка единого идентификатора беспроводной сети для разных регионов
Укажите отдельную звонилку для рабочего профиля

Доступ к рабочим контактам в профилях

EMM могут разрешить личному профилю пользователя доступ к его рабочим контактам, чтобы личные и рабочие контакты пользователя были доступны через локальный поиск и поиск в удаленном каталоге. На персональных устройствах один номеронабиратель в личном профиле может совершать и принимать как личные, так и рабочие звонки. Кроме того, рабочие контакты хорошо интегрированы в пользовательский интерфейс системы. Если рабочий профиль зашифрован, его данные недоступны для личного профиля.

Интегрирован с системным пользовательским интерфейсом

Системный пользовательский интерфейс обозначает входящие рабочие звонки с помощью значка портфеля. В callLog также отображается значок для обозначения входящих и исходящих рабочих вызовов. Приложения для личного набора номера и контактов могут отображать информацию об идентификаторе вызывающего абонента рабочего контакта с помощью поиска в удаленном каталоге, поэтому не требуется, чтобы контакт уже был синхронизирован на локальном устройстве. Приложение для обмена сообщениями может выполнять локальный идентификатор вызывающего абонента и выполнять поиск.

Документ определения совместимости Android (CDD) включает требования к отображению рабочих контактов в номеронабирателе по умолчанию, а также требования к тому, чтобы контакты и приложения для обмена сообщениями были отмечены значками, указывающими, что они из рабочего профиля.

Рабочие контакты доступны и доступны для поиска

Пользователь может получить доступ к рабочим контактам и позвонить им из своего личного профиля, который отображается на экране поиска приложения для набора номера. Пользователь может искать рабочие контакты (с помощью автозаполнения), которые синхронизируются локально с устройством и перечислены посредством поиска в удаленном каталоге.

Контролируйте рабочие контакты в основном профиле

ЦОД контролирует разрешение на поиск рабочих контактов. Работая в режиме владельца профиля, ЦОД управляет видимостью рабочих контактов в личном профиле. Дополнительные сведения см. в разделе Создание контроллера политики устройства .

Поиск рабочих контактов по личному профилю включен по умолчанию.

Обеспечьте безопасное сетевое соединение для рабочего трафика.

Работая либо в режиме владельца устройства, либо в режиме владельца профиля, контроллер политики устройства может использовать постоянное подключение к виртуальной частной сети (VPN), чтобы заставить приложения пропускать трафик через указанное приложение VPN, которое невозможно обойти. Используя постоянное VPN-соединение, ЦОД может гарантировать, что сетевой трафик из рабочего профиля или управляемого устройства проходит через службу VPN без вмешательства пользователя. Этот процесс создает безопасное сетевое соединение для непрерывного трафика в рабочем профиле.

О постоянных VPN-соединениях

В рамках системной структуры маршрутизация VPN управляется автоматически, поэтому пользователь не может обойти службу VPN. Если служба VPN отключена в режиме блокировки, трафик не может просачиваться в открытый Интернет. Для приложений, реализующих VpnService , постоянная VPN обеспечивает основу для управления безопасным VPN-соединением через доверенный сервер и поддержания его работоспособности. Служба VPN автоматически перезапускает соединение при обновлении приложения независимо от того, установлено ли соединение по Wi-Fi или по сотовой сети. А если устройство перезагрузится, фреймворк перезапустит VPN-соединение.

Подключение к VPN-сервису прозрачно для пользователя. Для устройства, принадлежащего компании, пользователю не требуется подтверждать диалог согласия для VPN в постоянном режиме. Настройки сети VPN пользователя позволяют вручную включить постоянное соединение.

Если DISALLOW_CONFIG_VPN имеет значение true , пользователю не разрешается настраивать VPN. Включите DISALLOW_DEBUGGING_FEATURES , чтобы запретить пользователям переопределять постоянно включенный VPN с помощью команды отладки adb. Чтобы запретить пользователю удалить VPN, вызовите DevicePolicyManager.setUninstallBlocked .

Настройте VPN-сервис

Организация, которая использует ваше корпоративное решение для Android, настраивает VPN.

  1. Установите приложение VPN, реализующее VpnService . Вы можете найти активные службы VPN, используя фильтр намерений, соответствующий действию VpnService.SERVICE_INTERFACE .
  2. Объявите VpnService в манифесте приложения, защищенном разрешением BIND_VPN_SERVICE .
  3. Настройте VpnService так, чтобы он запускался системой. Не настраивайте приложение VPN на самозапуск, прослушивая загрузку системы и контролируя свой жизненный цикл.
  4. Установите управляемые конфигурации для приложения VPN (см. пример ниже ).

Включить постоянное VPN-соединение

ЦОД может настроить постоянное VPN-соединение через определенное приложение, вызвав DevicePolicyManager.setAlwaysOnVpnPackage() .

Это соединение предоставляется автоматически и сохраняется после перезагрузки. Если lockdownEnabled имеет значение false, сетевой трафик может быть незащищенным с момента перезагрузки телефона и подключения VPN. Это полезно, если вы не хотите прекращать сетевое подключение при сбое VPN или если VPN не является обязательным.

Проверьте постоянное VPN-соединение

ЦОД может прочитать имя пакета, администрирующего постоянное VPN-соединение для текущего пользователя, с помощью DevicePolicyManager.getAlwaysOnVpnPackage() .

Если такого пакета нет или VPN был создан в приложении системных настроек, возвращается null .

Пример

В приложении TestDPC AlwaysOnVpnFragment.java использует эти API, чтобы включить настройку постоянного VPN-соединения.

В следующем примере:

  • Управляемые конфигурации службы VPN задаются DevicePolicyManager с помощью метода setApplicationRestrictions() .
  • В управляемых конфигурациях используются произвольные пары «ключ-значение», и в этом примере приложения они используются в другом месте для настройки сетевых параметров VPN (см. Проверка управляемых конфигураций ).
  • В этом примере установщик пакетов Android добавляется в список запрещенных, чтобы он не обновлял системные пакеты через VPN. Весь сетевой трафик пользователя в рабочем профиле или устройстве проходит через это VPN-приложение, за исключением установщика пакетов; его обновления используют открытый Интернет.
  • Затем DevicePolicyManager включает постоянное VPN-соединение для пакета VPN с помощью setAlwaysOnVpnPackage() и включает режим блокировки.

Котлин

// 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()
}

Ява

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

Настройка единого идентификатора беспроводной сети для разных регионов

Контроллер политики устройства (DPC), работающий либо в режиме владельца устройства, либо в режиме владельца профиля, может связать несколько сертификатов центра сертификации (CA) с одной конфигурацией беспроводной сети. При такой конфигурации устройство может подключаться к точкам беспроводного доступа, которые имеют одно и то же имя сети или идентификатор набора служб (SSID), но настроены с использованием разных сертификатов CA. Это полезно, если беспроводные сети вашей организации расположены в нескольких географических регионах и для каждого региона требуется отдельный центр сертификации. Например, для юридических подписей может потребоваться местный орган власти, которому нужен региональный центр сертификации.

Примечание. Android поддерживает setCaCertificate начиная с API 18 (Jelly Bean), но ИТ-администраторы должны подготавливать свои сети отдельно для каждого центра сертификации, чтобы обеспечить бесперебойную аутентификацию устройств в каждой точке доступа, независимо от их региона.

Укажите сертификаты CA для идентификации сервера

Чтобы указать список сертификатов X.509, которые идентифицируют сервер с использованием одного и того же SSID, включите все соответствующие центры сертификации в конфигурацию беспроводной сети с помощью WifiEnterpriseConfig.setCaCertificates() .

Сертификат сервера действителен, если его центр сертификации соответствует одному из данных сертификатов. Имена по умолчанию автоматически назначаются сертификатам и используются в конфигурации. WifiManager устанавливает сертификат и автоматически сохраняет конфигурацию при включении сети и удаляет сертификат при удалении конфигурации.

Чтобы получить все сертификаты CA, связанные с конфигурацией беспроводной сети, используйте WifiEnterpriseConfig.getCaCertificates() , чтобы вернуть список объектов X509Certificate .

Добавьте конфигурацию беспроводной сети с использованием нескольких сертификатов CA.

  1. Подтвердите личность сервера:
    1. Загрузите сертификаты CA X.509.
    2. Загрузите закрытый ключ и сертификат клиента. См. раздел «Безопасность с помощью HTTPS и SSL», где приведен пример чтения файла сертификата.
  2. Создайте новую WifiConfiguration и установите ее SSID и управление ключами.
  3. Настройте экземпляр WifiEnterpriseConfig в этом WifiConfiguration .
    1. Определите сервер со списком объектов X509Certificate , используя setCaCertificates() .
    2. Установите учетные данные, удостоверение и пароль клиента.
    3. Установите расширяемый протокол аутентификации (EAP) и метод фазы 2 как часть установления соединения.
  4. Добавьте сеть с помощью WifiManager .
  5. Включите сеть. WifiManager автоматически сохраняет конфигурацию во время установки.

Этот пример связывает шаги вместе:

Котлин

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

Ява

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

Укажите отдельную звонилку для рабочего профиля

Вы можете внести в список разрешенных отдельное приложение для набора номера, которое будет использоваться в рабочем профиле. Это может быть сам номеронабиратель или приложение Voice over IP (VoIP), которое реализует API ConnectionService для вызывающей серверной части. Это обеспечивает тот же интегрированный интерфейс набора номера через системный интерфейс для приложений VoIP в рабочем профиле, что фактически делает рабочий номеронабиратель основной функцией. Входящие вызовы на рабочие учетные записи отличаются от входящих вызовов на личные учетные записи.

Пользователь может совершать и принимать звонки с рабочего номера, включенного в разрешенный список, в учетной записи телефона. Все вызовы, сделанные с этого номера или входящие на учетную запись рабочего телефона, записываются в поставщике CallLog рабочего профиля. Рабочий номеронабиратель ведет журнал вызовов только для рабочих с доступом только к рабочим контактам. Входящие вызовы коммутатора каналов обрабатываются основным номеронабирателем и сохраняются в личном журнале вызовов. Если рабочий профиль удаляется, журнал вызовов, связанный с этим рабочим профилем, также удаляется, как и все данные рабочего профиля.

Сторонние приложения должны реализовывать ConnectionService.

Сторонние приложения VoIP, которым необходимо совершать телефонные звонки и интегрировать эти вызовы во встроенное телефонное приложение, могут реализовать API ConnectionService . Это необходимо для любой услуги VoIP, используемой для рабочих звонков. Эти приложения выигрывают от того, что их вызовы обрабатываются как традиционные вызовы сотовой связи: например, они отображаются во встроенном системном номеронабирателе и в журнале вызовов. Если приложение, реализующее ConnectionService , установлено в рабочем профиле, оно доступно только для программы дозвона, также установленной в этом рабочем профиле.

После того как разработчик реализовал ConnectionService , он должен добавить его в файл манифеста приложения и зарегистрировать PhoneAccount в TelecomManager . Учетная запись телефона представляет собой отдельный метод совершения или приема телефонных звонков, и для каждой ConnectionService может быть несколько PhoneAccounts . После регистрации учетной записи телефона пользователь может включить ее через настройки звонилки.

Интеграция системного пользовательского интерфейса и уведомлений

Системный пользовательский интерфейс предоставляет пользователям единообразный и интегрированный интерфейс набора номера для сторонних приложений, которые используют API ConnectionService в качестве серверной части для совершения вызовов. Если вы используете приложение в рабочем профиле, значок портфеля отображается при входящих вызовах и в строке состояния. Приложение, реализующее ConnectionService , установленное в рабочем профиле, может использовать системный номеронабиратель или создать отдельный рабочий дозвонщик. Это может быть одно приложение или отдельные приложения.

Приложение дозвона определяет, совершает или принимает рабочий вызов, проверяя флаг android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL . Если звонок является рабочим, звонилка сообщает об этом пользователю, добавляя рабочий значок (значок портфеля):

Котлин

// 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
}

Ява

// 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
}