Меня зовут Павел Медведев, я занимаюсь поддержкой B2B-клиентов в компании Samsung и пишу про это в блоге Samsung на Хабре. Сегодня я в гостях у коллег из SafeMobile — мы давно работаем вместе, а в их версии SM16 появилась удобная настройка MDM-плагинов, так что повод показать её в деле нашёлся сам собой.
Google год за годом переводит корпоративное управление Android на свои облачные рельсы, и писать собственного MDM-агента становится всё труднее: часть старых интерфейсов уже отключена, а тот агент, который вы всё-таки написали, с прошлого года может просто не установиться на устройство — его может заблокировать Google Play Protect. Если вы сопровождаете мобильный парк на MDM-решении, которого нет в списке крупных вендоров, это касается вас напрямую.
У Samsung на этот случай есть свои механизмы: собственный QR-код для регистрации устройств и Knox Service Plugin для их настройки. Под катом — что именно Google закрутил, что Samsung предлагает взамен и как через KSP настроить то, чего может не быть в вашем MDM. Планшеты, которые сами включаются, когда в них воткнули питание, и гаснут, когда в магазине выключили свет. Ограничение заряда 80%, чтобы у витринной техники не летели аккумуляторы. Эти и другие примеры ждут вас под катом.

Как Google закручивал гайки
Начнём с фактов, а выводы каждый сделает сам.
Управление Android-устройством работает через MDM-агент — приложение, которое получает специальные права и применяет политики. Написать своего агента можно было всегда, и десятки продуктов, включая российские, так и сделаны.
Дальше следите за руками. Сначала Google закрыл доступ к библиотекам Play EMM API, с помощью которых MDM-агенты могли создавать на устройствах корпоративные Google-аккаунты и устанавливать приложения из Google Play. Взамен предложили Android Management API (AMAPI) – облачный интерфейс от Google: политики доставляются на устройство не с вашего MDM-сервера, а через облако Google, и применяет их на телефоне MDM-агент от Google.
Пару слов про AMAPI. По сути, это закрытый контур, где устройство подключено к серверу Google, а ваш MDM сервер просит Google применить какие-то политики, и доверяет ответам, хотя не может их проверить. В этом контуре Google решает, какие функции должны быть в вашем MDM – если чего-то нет или новое требование Google не было вовремя реализовано, вы рискуете остаться без управления своими устройствами. Причём неважно, нужна вам или кому-то другому новая обязательная функция от Google или нет 🤷.
После AMAPI появился список одобренных агентов: во время подключения устройства по стандартной схеме Android Enterprise разрешены только те, которые Google проверил и внёс в этот список. Всех остальных встречает Play Protect с сообщением «Обнаружено вредоносное приложение». Включили это в 2025 году без предупреждения — сегодня подключение по QR-коду работает, завтра пользователь на складе видит, что делает что-то вредоносное. Практический результат я наблюдал своими глазами: на Android 16 агент по стандартному Android QR-коду уже не ставится, и я знаю команды, которые смирились с установкой через adb, потому что другого пути не нашли.
Попасть в список может любой разработчик — быть партнёром Android Enterprise для этого не обязательно. Готовить к заявке нужно примерно следующее: имя пакета и ссылку на APK, отпечаток сертификата подписи, объяснение, зачем ваш агент нужен и что он делает на устройстве, обоснование каждого чувствительного разрешения, политику конфиденциальности и, отдельным пунктом, доказательства, что вы занимаетесь корпоративным управлением, а не слежкой за людьми и не блокировкой телефона за неоплаченный кредит (сразу захотелось, правда?).
Какие есть ваши доказательства, что вы не верблюд. Регистрация в Google уведомительная или разрешительная. Очень даже второе и никаких гарантий в ответ.

Что есть на устройствах Samsung
Первое — свой способ подключить устройство. Вместо стандартного Android QR-кода Samsung умеет в KME Direct QR: тот же принцип, но JSON внутри заметно богаче, и в нём можно указать прямые ссылки на APK и на схемы политик. Никакого одобренного списка, никакого Play Protect на входе. Я разбирал этот механизм подробно в статье про то, как собрать MDM за 60 минут — там же лежит готовая JSON-схема, из которой QR-код генерируется хоть расширением для браузера.
Второе — Knox Service Plugin, он же KSP. Это обычное Android-приложение от Samsung, с помощью которого MDM настраивает всё то, что умеет Knox. Самое приятное, что он тоже приезжает по ссылке из того же KME QR-кода: Samsung рекомендует ставить KSP из Managed Google Play, но обязательным этот путь не является. А учитывая, насколько доступность Managed Google Play в России последние годы непредсказуема, запасной путь тут ценнее основного.
Дальше вся статья про KSP: зачем он появился, что через него настраивается и почему иногда молча не срабатывает. Примеры показываю на консоли SafeMobile (грех не воспользоваться гостеприимством хозяев), но механизм одинаков для любого MDM, который умеет доставлять вложенные словарные конфиги в managed configuration или, иначе, AppConfig.
Зачем понадобился плагин
У производителя устройств всегда была одна неприятная развилка. Допустим, Samsung выпустил корпоративную функцию — например, запрет или настройку какой-то фичи в новом One UI. Чтобы заказчик ею воспользовался, функцию должен поддержать его MDM. А у каждого MDM-вендора свои приоритеты и свой бэклог: одну и ту же возможность приходится продавать дважды — заказчику и разработчику MDM, который ещё неизвестно когда её реализует. Функция есть, а доехать до клиента не может.
Сначала был Knox SDK: в 2012-м Samsung представил SAFE и следом полноценный набор для разработчиков, который MDM-вендоры встраивали к себе. Между «Samsung добавил функцию» и «админ может ею пользоваться» лежали месяцы и чужой релиз-цикл. Кстати, про то, как Samsung вообще вытащил корпоративное управление Android на себе, пока Google смотрел в другую сторону, хорошо написано у коллег из SafeMobile в статье про четырнадцать лет корпоративной мобильности.
Затем появились OEMConfig плагины. Производитель выпускает собственное приложение-плагин, которое умеет принимать настройки от MDM через стандартный механизм AppConfig. MDM ничего не знает про внутренности Knox — он просто доставляет в приложение конфигурацию, а применяет её на устройстве сам плагин. Появилась новая политика у Samsung — она приехала вместе с новой версией приложения, и любой MDM, умеющий доставлять конфигурацию, подхватил её без единой строчки доработок у себя. Подробно про сам механизм я писал в отдельной статье — Магия KNOX и её разоблачение. С OEMConfig есть один нюанс – чаще всего это конфигурации со сложной вложенной структурой, поэтому если ваш MDM умеет доставлять только пары «ключ-значение», настроить KSP с его помощью, увы, не удастся.

KSP — это и есть OEMConfig-приложение от Samsung. Дальше я буду называть его то плагином, то приложением KSP — это одно и то же: обычный APK, который стоит на устройстве и виден в списке приложений.

Две вещи про устройство плагина, которые потом экономят часы на диагностике:
Шаблон настроек MDM берёт из самого APK — внутри лежит описание всех доступных политик. Отсюда требование: версия APK, из которой собран шаблон в консоли, должна совпадать с версией KSP на устройстве. Старый плагин не понимает схему новее себя и честно падает с ошибкой 12002.
KSP — посредник, сам он ничего не решает. Применилась политика или нет, по-настоящему знает только устройство. Поэтому, когда что-то идёт не так, смотреть надо в трёх местах: дошла ли конфигурация, что ответил плагин и что в итоге сделало устройство. К диагностике вернёмся в конце.
И ещё до всякого JSON проверьте привилегии агента на устройстве. Политики уровня устройства требуют режима Device Owner, политики рабочего профиля — Profile Owner. Если нужной привилегии нет, проблема в том, как устройство подключено, и никакая правка конфигурации не поможет.
Первая рабочая политика
Возьмём сквозной пример: запретить камеру и микрофон. Полная схема KSP — это сотни политик, но рабочую конфигурацию можно собрать из минимума. В SafeMobile есть два режима создания и редактирования конфигураций приложений — визуальный и текстовый. Для простоты приведу пример конфигурации в текстовом режиме:
{
"profileName": "KSP minimal test",
"verboseMode": true,
"kpePremiumLicenseKey": "",
"doPolicies": {
"doRestrictions": {
"doRestrictionMic": false,
"doRestrictionCamera": false,
"doRestrictionsIsControlled": true
},
"doPoliciesIsControlled": true
}
}
Два нюанса, на которых спотыкаются все.
Смысл политик инвертирован. Здесь false означает «запрещено»: doRestrictionCamera: false — камера выключена. В голове у автора схемы это читалось как ответ на вопрос «разрешить камеру? нет», но в JSON выглядит ровно наоборот тому, чего ожидаешь, и включить камеру вместо её запрета проще простого. Цепочка *IsControlled. Чтобы блок применился, флаги-выключатели должны стоять по всей вложенности: и на ветке (doPoliciesIsControlled), и на блоке (doRestrictionsIsControlled). Нет любого звена — блок молча игнорируется, даже если значения заданы верно. Это первое, что стоит проверить, когда «ничего не происходит, и ошибок тоже нет».

Поле verboseMode: true делает плагин видимым на устройстве и включает экран с результатами применения — для отладки незаменимо. В бою его выключают, и тогда KSP с экрана пропадает.
Что через KSP настраивается
Политик в Knox сотни, и с каждой версией плагина их становится больше, поэтому полной поддержки Knox нет ни у одного MDM в мире — это гонка, в которой невозможно финишировать. Нативные MDM-профили закрывают то, что нужно большинству, а KSP открывает всю ветку целиком, включая то, до чего галочки ещё не добрались, и премиальные политики Knox, и свежие возможности, которые приезжают с обновлением плагина раньше, чем появляются где-либо ещё.
Дальше — кейсы из практики, те, что приходили ко мне в работу.
Киоск, который сам включается и гаснет
Пара политик в блоке doSettings:
"doSettings": {
"doSettingsIsControlled": true,
"doSettingsAutoStartUp": true,
"doSettingsPowerOFF": true
}
doSettingsAutoStartUp поднимает устройство само, как только появляется питание; doSettingsPowerOFF гасит его, когда питание пропадает. Нужно технике, которая висит на постоянном подключении: например, рекламные планшеты в такси. Или сценарий из розницы — вечером последний продавец вышел, выключил свет, все планшеты погасли; утром дали питание, поднялись сами. И сразу про главную сложность KSP: без doSettingsIsControlled: true и doPoliciesIsControlled: true выше блок не сработает.
Заряд не выше 80%
Для той же витринной техники, что сутками висит на зарядке:
"doDeviceCustomizationControls": { "doDeviceCustomizationIsControlled": true },
"profileDeviceCustomization": { "profileDeviceBatteryProtection": true }
Эти два кейса я показывал на пальцах в статье про MDM за 60 минут — там они собраны прямо в QR-код подключения, так что устройство приезжает к пользователю уже настроенным.
Выключить обновления ОС
Блок doFotaUpdate (doFotaUpdateOTA: false, doFotaUpdateAutoUpdate: false)глушит обновления по воздуху. Звучит еретически, но бизнесу, у которого приложение завязано на конкретную версию ОС, апдейт чаще ломает рабочий процесс, чем чинит. Просят постоянно. В SafeMobile то же самое доступно прямо в профиле ограничений Samsung Knox, без захода в JSON.
Запретить системе закрывать приложения при повышенном энергопотреблении
doAppMgmtBatteryWhitelist выводит пакеты из-под оптимизации батареи. Туда кладут MDM-агента, если он сам не умеет себя так защищать (SafeMobile — умеет); я на всякий случай добавляю и сам KSP (com.samsung.android.knox.kpu). В SafeMobile это же поведение настраивается правилами управления приложениями — там же, где вы их устанавливаете.
Список разрешённых приложений: по имени или по подписи
doAppMgmtWhitelistAppByName и doAppMgmtWhitelistAppBySignature — разрешать приложения по имени пакета или по подписи. Второе интереснее: подпись не подделать, поэтому под неё не подсунуть одноимённый пакет. Просили те, кому нужен по-настоящему жёсткий контроль над тем, что вообще может оказаться на устройстве.
Удалённая поддержка, которая иначе не заработает
Тут стоит остановиться подробнее, потому что это тот случай, когда без KSP не обойтись вообще никак.
Удалённая поддержка устройства — это показ экрана, чтобы инженер видел, что происходит у пользователя, и передача нажатий, чтобы он мог сам нажать нужную кнопку вместо него. В Knox SDK за это отвечают Remote Desktop и класс RemoteInjection соответственно. Показ экрана Samsung объявил устаревшим ещё в Knox SDK 3.8, передача нажатий жива, из неё выпали только методы для DeX — на Android 16 их уже нет.
Но главное не это. С Android 15 и Knox 3.11 Samsung ограничил удалённое управление: пользоваться им могут только приложения, работающие как Device Owner или Profile Owner либо внутри управляемого ими окружения, и только если администратор явно выдал такое право. У Samsung есть отдельная инструкция ровно про эту ситуацию, и способ выдать право там описан ровно один — через KSP:
"profileAppMgmtAddApplicationsToAccessSdk": [
{
"profileAppMgmtAddPackageNameToAccessSdk": "ваш.пакет",
"profileAppMgmtAddScopeToAccessSdk": ["authorization_remote_control"]
}
]
Без этих строк ваш инструмент удалённой поддержки на свежих Samsung ведёт себя непредсказуемо или не работает совсем — и никакая лицензия, никакие разрешения в манифесте и никакие правильные режимы управления его не спасут. Именно так это и выглядит на практике: всё сделано верно, а поддержка не подключается. Через ту же дверь заходят TeamViewer и Splashtop — у обоих в базе знаний лежат инструкции, как включить себе удалённое управление на Samsung через OEMConfig.
Вот вам и ответ, зачем нужен плагин: он бывает единственным способом получить то, что прикрыто со всех остальных сторон. А у SafeMobile, кстати, агент удалённой поддержки встроен в продукт и работает прекрасно — поскольку эта функция встроена в агент управления, KSP ему для работы не нужен. Но unattended вариант, когда разрешение пользователя не требуется, можно сделать только через этот путь или через метод разработчиков SafeMobile. Это для тех случаев, когда админ поддержка работает во внерабочее время, подключаясь к устройствам, стоящих на зарядке.
Скрытые опции: то, чего может не быть на экранной форме
Настройки, которые вы видите в консоли, MDM берёт из схемы внутри APK: разбирает её и рисует по ней экран с галочками, списками и полями. Всё, что в схему попало, вы найдёте либо там, либо в текстовом шаблоне. А есть различные перечисления (enum), которых в шаблоне нет. Задать их часто можно только вручную, по имени, через массив profileDeviceSettingsConfigItems. Два примера, которые реально выручали в поле:
"profileDeviceCustomization": {
"profileDeviceSettingsConfigItems": [
{
"profileDeviceSettingsConfigName": "disable_connectivity_check",
"profileDeviceSettingsConfigOnoff": "ON"
},
{
"profileDeviceSettingsConfigName": "screen_timeout",
"profileDeviceSettingsConfigOnoff": "SPECIFIC_VALUE",
"profileDeviceSettingsConfigValue": "86400000"
}
]
}
disable_connectivity_check отключает проверку интернета. Android периодически дёргает www.google.com/generate_204, чтобы понять, есть ли сеть. А теперь представьте организацию — пальцем показывать не буду, — где стоит firewall с инспекцией TLS: он переупаковывает шифрованный трафик на своих прокси, чтобы держать его под контролем. Если в исключения не добавить этот адрес, Android замечает подмену сертификата и решает, что интернета нет, хотя сеть есть. Отключение самой проверки это лечит.
screen_timeout задаёт таймаут экрана сверх системного потолка. Штатно Android разрешает максимум полчаса, а через KSP можно поставить сколько угодно — на сутки точно. Нужно некоторым реализациям киоска, которые сами не справляются с гаснущим экраном (в SafeMobile не нужно — примечание ред.). Причину такого безобразия не назову: фирменный пакет Knox для киоска ProKiosk с этим прекрасно справляется без костылей, но не все построены на нём.
Всего таких ключей в profileDeviceSettingsConfigItems около семидесяти. Узнать о них можно из выпадающих списков в Knox Manage, родной консоли Samsung, либо вытащив прямо из пакета KSP — там лежит весь список с допустимыми значениями. Разбор пакета тут обычный рабочий способ: я в своё время натравил на него ИИ-ассистента, задал правильные вопросы, он мне всё и вытащил.
Две вещи, на которых там легко обжечься. Первая: имена ключей пишутся символ в символ, включая опечатки разработчиков — параметр чувствительности касания называется increse_touch_sensetivity, с двумя ошибками в одном слове, и только так он и сработает. Вторая: значения всегда строки, даже числовые — screen_timeout задаётся как "86400000" в кавычках, перепутаете тип и поймаете ошибку 33000. Чтобы разобраться во всем этом пришлось поковырять немного с jadx сам плагин.
Кстати, в SafeMobile это всё настраивается — ребята умеют разбирать в конфигурации в том числе перечисления, поэтому настройка этого параметра в их продукте выглядит так:

Где у KSP граница
Иногда упираешься в потолок самого плагина. Пример — Separated Apps, раздельные пространства приложений на одном устройстве. В KSP эта ветка сильно урезана: по сути, можно лишь перечислить приложения, без тонких правил вроде «эти приложения должны быть в обоих пространствах». Подробно про сам сценарий — изоляцию мессенджеров в отдельном пространстве — я писал в отдельной статье. Если Separated Apps нужны всерьёз, я рекомендую вместо KSP отдельный AppConfig-пакет com.samsung.androd.appseparation: он предустановлен на устройствах, и схема у него заметно богаче.
Подвох всплыл, как только этим начали пользоваться. Внутри пространства Separated Apps нет магазина приложений, а вместе с ним внутрь не попадают и компоненты Google Play, от которых зависит распознавание QR-кодов через библиотеки ML Kit. На практике это значит, что приложение, которое пускает в десктопную версию по QR-коду, в таком пространстве этот код не отсканирует. Привет, например, десктопному входу в мессенджер MAX, и не только ему.
Руками это лечится командой adb shell install-existing, и на одном устройстве такой способ действительно работает. Штатным его не назовёшь: Google подобное не приветствует, а главное — из MDM-агента так сделать нельзя в принципе. Приложение не может выполнить adb-команду само против себя: для adb нужен включённый пользователем режим отладки и компьютер на другом конце провода. Ближайший легальный аналог в Android — метод installExistingPackage, доступный MDM-агенту в режиме Device Owner или Profile Owner, но он ставит приложение для того пользователя, от имени которого вызван, а Separated Apps живёт в отдельном пользовательском пространстве.
Так что честный ответ — штатного пути нет. Единственный одобренный Samsung установщик для этого пространства — Managed Google Play, а с ним в России не задалось. Остаётся либо ставить руками через adb, либо не загонять в Separated Apps приложения, которым нужен QR.
Когда политика не применяется
KSP не капризен, но настраивается нетривиально, и сбой почти никогда не выглядит как явная ошибка. Чаще это «успех, а эффекта нет»: конфигурация уехала, плагин отрапортовал, а камера, которую надо было запретить, как работала, так и работает. Дальше о том, как это правильно дебажить.
Дошла ли конфигурация. В консоли SafeMobile у устройства есть вкладка с конфигурациями приложений и столбец «Применена». «Да» — доставлена; «устаревшая» — на устройстве лежит версия постарше; «Нет» — не доехала вовсе. Если «Нет», проблема на транспорте, до KSP дело ещё не дошло, и копаться в JSON рано.
Что ответил плагин. Android умеет возвращать в MDM обратную связь от приложения — плагин шлёт результат через стандартный механизм Application Feedback. SafeMobile его поддерживает, поэтому для выбранного устройства ответ плагина можно посмотреть на вкладке «Фидбэк приложений». Этот канал обратной связи работает всегда, независимо от verboseMode.
Что показывает устройство. При verboseMode: true открываем приложение KSP на смартфоне и заходим в Configuration results. Успешные политики — чёрным, упавшие — красным, с кодом и текстом ошибки. Там же кнопка Apply latest policies, чтобы переприменить без изменения конфигурации.

Лицензия и прокси
Отдельная история для закрытых контуров или не желающих зависить от активации лицензии где-то там за его пределами. KSP работает поверх фреймворка Knox Platform for Enterprise, и премиальные политики требуют действующей лицензии KPE. Лицензия бесплатная: с 1 июля 2021 года Samsung отдаёт KPE заказчикам без денег, ключ выдаётся по запросу на samsungknox.com для использования в MDM агентах и на partner.samsungknox.com, если пишете свой. Либо её активирует сам MDM — в SafeMobile это видно в данных об устройстве, где привилегия «KNOX Premium» показана как «да», и тогда поле kpePremiumLicenseKey в JSON оставляют пустым. Либо MDM её не активировал, и тогда ключ вписывают в это поле, а KSP активирует его при применении конфигурации. Активация стучится на сервер лицензий Samsung gslb.secb2b.com — и вот тут в закрытых контурах начинается самое весёлое. За глобальным прокси запрос до сервера не доходит, активация падает с ошибкой 13005, а вместе с ней тихо отваливаются все премиальные политики. Это и есть классическая причина «политики не применяются, ошибок нет». Лечится добавлением сервера лицензий в исключения прокси. Если наружу нельзя совсем, у Samsung есть платный сервер лицензий для установки внутри периметра — берут и такое, гарантируя себе независимость от превратностей судьбы.

Что в итоге
Устройство подключается по KME Direct QR, даже если не находится в списке одобренных Google агентов (гайки продолжат завинчиваться, в этом мало кто сомневается). Настройки приезжают в KSP, который можно доставить как с помощью MDM, так и с помощью QR-кода. В Google при этом обращаться не нужно ни разу. Официальных документации по интеграции KSP помимо Managed Google Play, но кто знает что такое AppConfig официальная документация и не нужна. По крайней мере, в команде SafeMobile разобрались во всём самостоятельно.
Плата за независимость — работа с сырым JSON и диагностика, которая начинается со слов «ошибок нет, но что-то не работает». Первое MDM берёт на себя ровно в той мере, в какой умеет разбирать схему плагина: в SafeMobile руками JSON писать не приходится. Второе лечится дисциплиной: проверьте версию KSP на устройстве, проверьте доступ к серверу лицензий и только потом ищите ошибку в конфигурации. Её там, скорее всего, нет.
А если у вас есть свой сценарий, который штатными галочками не собирается, — напишите в комментариях, разберём его вместе.

