Что такое dsu loader на андроид
Перейти к содержимому

Что такое dsu loader на андроид

  • автор:

DSU Loader — что это и зачем нужно в смартфоне?

Принцип работы функции DSU Loader в режиме разработчика на телефоне.

Режим разработчика на смартфоне необходим для более детальных настроек мобильного телефона, но не все его функции понятны простому пользователю. Расскажем, что такое «DSU Loader», за что эта функция отвечает и нужно ли ее активировать.

Что такое DSU Loader в смартфоне?

Один из пунктов меню для разработчиков, который часто вызывает вопросы у пользователей, называется DSU Loader. Эта функция полноценно была введена в версии Android 11 и расшифровывается как «Dynamic System Updates» или «динамическое обновление системы». Задача этой функции — установить на смартфон системный образ новой ОС (GSI), который включает как саму операционную систему, так и настройки, конфигурации и все программы, установленные на нее.

Простыми словами, DSU Loader позволяет временно протестировать новую версию Android без полной перепрошивки устройства. При этом текущая версия ОС, а также фирменная оболочка производителя остаются нетронутыми и не подвергаются никакому риску. После того, как пользователь ознакомится со всеми функциями новой версии Android, он сможет так же легко вернуться к своей старой ОС — для этого понадобится всего лишь перезагрузить смартфон.

DSU Loader максимально упрощает процесс тестирования новой версии Android как для разработчиков приложений, так и для простых пользователей, которые хотят ознакомиться со свежей ОС и ее функциями, чтобы решить, стоит ли она полноценной установки. И если раньше для подобного теста требовалось использование команд ADB или Fastboot, то с появлением функции DSU Loader для установки необходимо всего несколько нажатий.

Как активировать DSU Loader на смартфоне?

Возможность установить и протестировать новую версию ОС появится, только если соблюдены несколько факторов:

  • Системный образ ОС должен быть подписан Google или производителем смартфона.
  • Функция DSU Loader должна быть добавлена в настройки смартфона производителем мобильного устройства.

Функция доступна на большинстве современных телефонов, а найти ее можно в режиме для разработчиков. Для этого его необходимо активировать, нажав на номер сборки устройства 5-7 раз — этот пункт находится в разделе «О телефоне».

DSU Loader DSU Loader

Далее в основном меню настроек нужно найти пункт «Для разработчиков» (он может находиться в разделе «Дополнительные» или «Расширенные» настройки) и среди настроек найти строку DSU Loader. Теперь остается выбрать один из предложенных образов в зависимости от архитектуры устройства и установить его, следуя инструкции. Чтобы вернуться к исходной ОС, достаточно перезагрузить смартфон.

Android 13 улучшит DSU — установка общей системы GSI в два раза быстрее

Динамическое обновление системы (DSU) — одна из малоизвестных функций Android. Эта функция позволяет пользователям устанавливать общий образ системы (GSI) без разблокировки загрузчика или установки системных обновлений. Это упрощает переключение между текущим образом системы и GSI. Впервые представленная в Android 10, эта функция является одним из самых простых способов для разработчиков протестировать последнюю версию Android 13. Согласно информации от технического эксперта Мишаала Рахмана, DSU получит улучшения в Android 13.

Android 13 1024x470

Новый коммит от AOSP Gerrit предполагает, что Google вносит заметные улучшения производительности в DSU. Установка GSI через DSU выполняется намного быстрее за счет увеличения общей памяти по умолчанию . Google отмечает, что небольшое увеличение объема памяти (с 8 КБ до 64 КБ) значительно ускорит динамическую установку системы как на физических, так и на виртуальных устройствах.

Тесты Google показывают, что время установки на физическом устройстве сокращается с 2 минут и 2 секунд до 45 секунд. Кроме того, время установки на виртуальное устройство сокращается с 45 до 30 секунд.

Кроме того, индикатор выполнения также получил некоторые новые улучшения. Во время установки GSI индикатор выполнения в центре уведомлений будет показывать устанавливаемый раздел . В текущей версии Android 13 отображается только «Установка». DSU также добавит поддержку образов system, system_ext и продуктов. Эти функции и улучшения пока недоступны в Android 13 Developer Preview.

Android 13 a

Android 13 будет изначально поддерживать открытие нескольких карт eSIM на одном чипе.

Традиционные мобильные телефоны используют физическую карту (SIM-карту) для подключения к сотовой сети. Тем не менее, цифровая карта eSIM не развивается быстро, отчасти потому, что она не полностью совместима с Android. Согласно новому отчету Esper, Google может внедрить eSIM в Android 13 , чтобы повысить популярность этой технологии. Эспер сообщает, что кодовая база Android 13 содержит патент, поданный Google в 2020 году, который позволяет использовать несколько профилей SIM-карт на одном встроенном чипе .

Согласно патентному описанию, это достигается за счет разделения единой физической шины данных между модемом и чипом eSIM на несколько логических интерфейсов, которые затем объединяются в один физический интерфейс. Это похоже на то, что современные ЦП разделяют физические ядра ЦП на логические ядра ЦП для одновременного выполнения большего количества задач. В отличие от физической SIM-карты, которая должна быть оснащена слотом, для eSIM требуется только небольшой компонент на материнской плате, что оставляет больше места для размещения в телефоне более крупных аккумуляторов, оборудования камеры или других компонентов. Однако не многие телефоны полностью отказались от физического слота для SIM-карты.

Интересные видео

Белоснежка в законе. Веселая сказка на пару минут

В городском королевстве проживала королева, известная своей красотой и жаждой подтверждения своего величия. Ее воле было подвластно волшебное зеркало, которое отвечало на ее вопросы. Но однажды зеркало объявило, что истинной красавицей королевства является не она, а приемная дочь Белоснежка.

Динамические и модульные обновления Android

android

Эта статья рассказывает о ряде технологий, которые были интегрированы в Android в последние несколько лет и приблизили решение проблемы фрагментации, отсутствия обновлений и существенно упростили создание кастомных прошивок.

A/B-разметка

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

В свое время разработчики Chrome OS также столкнулись с этой проблемой и создали надежную и незаметную пользователю систему бесшовного обновления (Seamless updates). Суть ее состоит в том, что вместо одного системного раздела, поверх которого накладывались бы обновления системы, Chrome OS использует два идентичных системных раздела, каждый из которых содержит свою копию операционной системы.

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

Благодаря такой схеме пользователь даже не подозревает, что система обновилась, он просто попадает в обновленную ОС после перезагрузки или включения ноутбука. При этом Chrome OS способна гарантировать, что после обновления пользователь не получит кирпич: если во время загрузки с обновленного раздела произойдет сбой — система пометит текущий раздел флагом unbootable, сделает активным «старый» системный раздел и загрузит заведомо рабочую версию ОС.

Начиная с седьмой версии Android также поддерживает бесшовные обновления и так называемую A/B-разметку разделов. Однако, так как системных разделов в устройствах с Android намного больше, чем в хромбуках, сама раскладка разделов получается более запутанной. Вот только часть разделов, которые пришлось дублировать:

  • boot — содержит ядро и RAM-диск, на устройствах с A/B-разметкой также консоль восстановления (recovery);
  • system — содержит Android, системные библиотеки, системные приложения, стандартные рингтоны, обои и так далее;
  • vendor — драйверы и все необходимые прослойки для работы с железом (Project Treble);
  • userdata — настройки, приложения и данные пользователя;
  • radio — прошивка радиомодуля (поддержка сотовых сетей);
  • vbmeta — раздел Android Verified Boot 2.0 (механизм доверенной загрузки), содержащий контрольные суммы компонентов системы.

Всего дублированных разделов может быть несколько десятков. Например, на OnePlus 6 с A/B-разметкой общее количество разделов — 72 и несколько десятков из них используются только загрузчиком.

От других разделов, наоборот, стало возможным отказаться. Устройства с A/B-разметкой не включают в себя отдельный раздел recovery (консоль восстановления, нужна для установки обновления и сброса до заводских настроек) и раздел cache , который использовался для хранения файлов обновлений (теперь обновление скачивается напрямую в неактивный раздел).

Двойные разделы на смартфоне OnePlus 6

A/B-разметка также позволила вдвое сократить размер раздела system , что вкупе с удалением разделов recovery и cache сделало переход на новую схему разметки менее болезненным. Например, на смартфонах Pixel потеря пространства составила всего несколько сотен мегабайт.

Раздел Размер A/B Размер A-only
Bootloader 50 Мбайт × 2 50 Мбайт
Boot 32 Мбайт × 2 32 Мбайт
Recovery 0 32 Мбайт
Cache 0 100 Мбайт
Radio 70 Мбайт × 2 70 Мбайт
Vendor 300 Мбайт × 2 300 Мбайт
System 2048 Мбайт × 2 4096 Мбайт
Всего 5000 Мбайт 4680 Мбайт

Еще одно достоинство A/B-разметки — отсутствие экрана «Android is upgrading…» после обновления. Система просто загружается как обычно. Также A/B-разметка упрощает тестирование кастомных прошивок: кастом можно поставить второй системой и откатиться на первую, если что-то пойдет не так.

В целом одни плюсы и никаких минусов. Проблема только в том, что A/B-разметка до сих пор остается опциональной, а перешли на нее далеко не все производители смартфонов. Даже Samsung — крупнейший производитель устройств на Android — до сих пор использует старую разметку. И связано это, скорее всего, с нежеланием тратить средства и время на перепрофилирование уже работающей и отлаженной системы обновления.

Проверить, поддерживает ли твой смартфон A/B-разметку, можно с помощью все того же приложения Treble Check из предыдущего раздела или прочитав переменную ro . build . ab_update с помощью ADB:

$ adb shell getprop ro . build . ab_update

Шпаргалка по управлению A/B-разделами с помощью fastboot

Узнать, какой слот (группа разделов) теперь активен:

$ fastboot getvar all | grep “ current — slot ”

Сделать неактивный в данный момент слот активным:

$ fastboot set_active other

Сделать активным указанный слот (a или b):

$ fastboot set_active СЛОТ

Прошить указанный раздел:

$ fastboot flash имя _ раздела _a partition . img
$ fastboot flash имя _ раздела _b partition . img

Динамические обновления

Project Treble открыл дорогу для еще одной весьма полезной функции — Dynamic System Updates (DSU). Этот механизм появился в Android 10 специально для пользователей и разработчиков, которые хотят протестировать новую (бета) версию Android, но не желают жертвовать для этого установленной системой и своими данными.

DSU базируется на технологии Dynamic Partitions, которая должна быть реализована во всех устройствах, выпущенных на рынок с Android 10. При использовании Dynamic Partitions в смартфоне, по сути, есть только один суперраздел, в котором система может создавать динамические разделы, удалять их и менять размеры (такое возможно благодаря модулю ядра Linux dm-linear).

Все системные разделы в таком смартфоне тоже динамические (кроме загрузочных разделов: boot, dtbo и vbmeta). Поэтому при необходимости система может сдвинуть их, чтобы освободить место для дополнительных разделов. Именно так делает функция DSU. Она уменьшает размер системных разделов, создает в освободившемся пространстве еще один набор системных разделов и устанавливает в него образ GSI. Далее смартфон перезагружается в эту свежеустановленную систему, а следующая перезагрузка выполняется вновь со стандартных разделов.

Чтобы установить образ GSI, используя DSU, для начала необходимо разблокировать загрузчик смартфона. Затем активировать DSU с помощью ADB:

$ adb shell setprop persist . sys . fflag . override . settings_dynamic_system true

Затем нужно скачать сам образ, распаковать и закинуть его на внутреннюю карту памяти смартфона:

$ gzip — c system_raw . img > system_raw . gz
$ adb push system_raw . gz / storage / emulated / 0 / Download /

Затем можно запустить установку:

$ adb shell am start — activity \
— n com . android . dynsystem / com . android . dynsystem . VerificationActivity \
— a android . os . image . action . START_INSTALL \
— d file : ///storage/emulated/0/Download/system_raw.gz \
— el KEY_SYSTEM_SIZE $ ( du — b system_raw . img | cut — f1 ) \
— el KEY_USERDATA_SIZE 8589934592

После окончания установки в шторке появится уведомление с предложением перезагрузиться.

Предложение перезагрузить смартфон после установки GSI

Сложно, не правда ли? Именно поэтому в Android 11 появилась функция под названием DSU Loader. Она позволяет автоматически загрузить и установить образ GSI в пару кликов.

В текущих сборках Android 11 DSU Loader требует разблокированный загрузчик. Однако к релизу стабильной версии Google планирует убрать это ограничение.

DSU Loader

Виртуальная A/B-разметка

Кроме возможности временной установки официальных сборок GSI, механизм DSU также позволил реализовать еще одну весьма интересную функцию — Virtual A/B.

Мы уже рассматривали преимущества новой A/B-разметки и то, какие проблемы она может решить. Однако ввиду потери пространства, которое может принести с собой A/B-разметка на устройствах с ограниченным объемом NAND-памяти, а также проблем с миграцией Google не спешит заставлять производителей смартфонов использовать новую разметку.

Вместо этого они создали виртуальную A/B-разметку. Работает она примерно так же, как динамические обновления, только без отката на ранее установленную прошивку: когда смартфон обнаруживает новое OTA-обновление, он создает несколько дополнительных системных разделов для новой прошивки, скачивает в них обновление, а затем делает эти разделы активными (как и в случае с A/B-разметкой). После следующей перезагрузки смартфон загружается уже с новых разделов; если загрузка проходит успешно, то старые разделы удаляются, а освобожденное ими место отдается разделу userdata.

Виртуальная A/B-разметка будет обязательной для всех устройств, вышедших на рынок с Android 11.

Модульные обновления

Еще один шаг в решении проблемы с обновлениями — Project Mainline. Это внедренная в Android 10 подсистема, позволяющая обновлять куски Android в обход производителя устройства.

В центре новой подсистемы — пакетный менеджер APEX, очень похожий на тот, что используется в дистрибутивах Linux и новой операционке Google Fuchsia. Работает он примерно так: допустим, по очередному указу правительства в России вновь меняют часовые пояса. Команда разработчиков Android формирует новую версию пакета с часовыми поясами и выкладывает ее в Google Play. Пользователи получают обновление — все счастливы.

Содержимое пакета APEX

Таким же образом могут быть обновлены библиотеки и целые подсистемы. Уже сейчас в AOSP доступны пакеты с рантаймом ART («виртуальная машина», ответственная за запуск приложений), библиотека криптографических алгоритмов Conscrypt, набор мультимедийных кодеков, мультимедийный фреймворк, DNS-резолвер, интерфейс Documents UI, Permission Controller, ExtServices, данные часовых поясов, ANGLE (прослойка для трансляции вызовов OpenGL ES в OpenGL, Direct3D 9/11, Desktop GL и Vulkan) и Captive Portal Login. В теории в пакет APEX можно упаковать практически любой компонент системы, и пользователи смогут обновить его независимо от производителя смартфона.

Интересно, что APEX не производит обновление «на живую», когда старый компонент заменяется новым. Раздел / system в Android недоступен для записи, поэтому APEX использует трюк с монтированием. Все обновляемые файлы внутри пакета APEX находятся в образе файловой системы ext4. Когда пакет «устанавливается», система монтирует этот образ поверх раздела / system в режиме bind. В результате файлы пакета как бы заменяют оригинальные файлы Android, хотя в реальности все остается на своих местах.

Такой же трюк использует Magisk для установки модификаций Android без изменения раздела / system . И его автор уже сказал, что APEX станет проблемой для Magisk.

«Установка» пакета APEX

Трюк с сохранением пространства

Внимательно прочитав раздел «A/B-разметка», ты мог заметить, что экономия пространства при такой разметке в основном достигается за счет сокращения размера раздела system в два раза. И дело здесь вовсе не в том, что при A/B-разметке используется какая-то специализированная сборка Android, а в отказе от «лишних» файлов.

В классическом варианте разметки системный раздел содержит в себе не только саму операционную систему, но и так называемые файлы odex. Они представляют собой оптимизированные (пропущенные через AOT-компилятор) версии dex-файлов, которые, в свою очередь, содержат код приложения.

Файлы odex позволяют сократить время старта приложения и повысить его производительность. Они могут быть созданы тремя путями:

  • преинсталлированы на устройство (в классическом варианте разметки — в раздел system);
  • сгенерированы динамически во время использования приложения или простоя устройства;
  • загружены из Google Play вместе с самим приложением.

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

Именно поэтому разработчики отказались от предустановки файлов odex в активный системный раздел, а вместо этого залили их в неактивный системный раздел вместо копии операционной системы. Так что жизненный цикл смартфона с A/B-разметкой выглядит так:

  1. При выпуске с конвейера раздел system_a активный, содержит файлы операционной системы, раздел system_b неактивный, содержит файлы odex.
  2. Во время первого запуска система копирует файлы odex в раздел userdata .
  3. После получения первого OTA-обновления система записывает обновление в раздел system_b , далее запускает генерацию файлов odex (инструмент dex2oat) для новой версии ОС (они также записываются в userdata) и после ее завершения помечает раздел system_b (все разделы слота B) как активный.
  4. После перезагрузки смартфон загружает операционную систему с раздела system_b , используя сгенерированные на третьем этапе файлы odex.

Выводы

A/B-разметка и динамические разделы — одни из самых интересных и полезных технологий, появившихся в Android в последние пять лет. В теории с их помощью можно реализовать мультизагрузку, создавать разделы для любых подсобных задач и полностью менять таблицу разделов устройства, выкинув все лишнее. Проблема только в том, что без разлочки загрузчика и кастомной прошивки все это будет недоступно.

APEX, с другой стороны, в теории может решить большинство проблем с обновлением смартфонов. Однако, в отличие от дистрибутивов Linux и ОС Fuchsia, пакеты APEX больше напоминают костыль, чем уместное инженерное решение. С другой стороны — лучше так, чем никак.

Мануал по установке почти любых GSI образов в качестве второй системы (aka DualBoot на современных смартфонах)

Не каждый наверное вспомнит, но раньше, на некоторых смартфонах (с наличием ROOT-прав) была возможность установки сразу же 2-х операционных систем на базе Android и переключаться между ними. Для чего это могло использоваться? Ну точного ответа дать я не могу, но в качестве примера, могу сказать, что таким образом можно было опробовать новую систему, не удаляя старую и не терять на ней важные вам данные.
Что же на счет современных устройств? Тут можно сказать спасибо компании Google за то что ввели такую замечательную функцию как DSU Loader (начиная с версии Android 11 и выше). Она позволяет опробовать новую версию системы не удаляя старую и не теряя данные. Грубо говоря, мы ставим так называемый Общий Образ Системы (GSI) от Google, рядом с основной системой и загружаемся в нее, дабы опробовать новые функции.
Но за такую прекрасную функцию мы расплачиваемся некоторыми особенностями. А именно: Разметка системных разделов в формате SAR A/B (Динамическая система разметки разделов, подробнее об этом вы можете прочитать в интернете) И открытый загрузчик. Как это сделать вы можете посмотреть на YouTube по запросу: «Как открыть загрузчик модель_устройства».
Итак, вы открыли загрузчик, Опробовали функцию в разделе разработчика (как открыть этот раздел читайте в интернете), но хотите другую прошивку, да и раздел для данных побольше? Хотя кого я обманываю, вы однозначно читали название статьи, верно?

Но как же установить кастомный GSI образ если нету кнопки выбора? Вот тут то нам и понадобится одна небольшая программа, а название ее DSU SideLoader! Эта замечательная программа позволит нам выбрать понравившийся GSI образ, и установить его в качестве второй системы, а так же выделить определенное количество памяти под данные, но ее косяк в том, что нужны ROOT-права на вашем устройстве (Как это делать, смотрите на YouTube). Есть еще конечно способ использовать данную утилиту без рут прав, через Shizuku, но лично я с этим не хотел заморачиваться, да и рут права у меня уже имеются, так что…. (Гугл вам в помощь).

Раз вы дочитали до этого момента, и у вас уже имеются рут-права и ваш смартфон соответствует необходимым требованиям (Напомню, ваш смартфон должен иметь Динамическую Систему разметки разделов SAR A/B и у вас должны быть установлены рут-права), то… вас ничего не остановит. А перед началом…

ДИСКЛЕЙМЕР.
Автор статьи не несет ответственности за поврежденные устройства и полученные кирпичи в следствии ваших действий. Автор не гарантирует стабильную работу на всех устройствах, везде будут те или иные баги, а они индивидуальны для каждого устройства. Вы все делаете на свой страх и риск.

Подготовка

Давайте представим, что вы выполнили необходимые условия и сразу же приступим…
В качестве подопытного я возьму Redmi 10 на официальной прошивке MIUI 12.5.3 RKUTWXM на базе Android 11, с установленным Magisk.
Для начала качаем утилиту под названием DSU SideLoader на официальном Github разработчика (качаем .apk самой последней из раздела Releases). Устанавливаем.

При первом запуске у нас запросят рут-права и доступ к внутренней памяти, все разрешаем, все предоставляем.

Теперь, нам необходимо создать папку для временных файлов, что бы программа правильно работала. Я (Что бы мне было удобно) создаю папку в внутренней памяти под названием «DSU-Folder» (без кавычек) и выбираю ее.

Далее подтверждаем, что загрузчик у нас открыт и видим главное меню программы. Можно приступать к установке…

Установка

Для начала, выбираем кастомную прошивку на базе ТОЙ ЖЕ версии Android что и ваша прошивка. У меня это Android 11, по этому я выбираю AOSP 11 phh v313. (Можете выбрать и Android 12+ но у меня не заработало). Прошивки берите на форуме из темы 4PDA.
Итак, мы скачали образ (Скорее всего он будет в архиве .xz но может и в .zip, тут индивидуально и смотря какую прошивку вы выбрали) и распаковали его. По итогу, мы должны получить файлик с расширением .img (это и есть наша система), в моем случае это «system-roar-arm64-ab-floss.img».

Теперь, мы возвращаемся в наше приложение, видим главное меню. В нем вы выбираем наш образ системы (Первая строчка Installation), а затем ставим галочку Userdata size и вписываем желаемый объем (Рекомендую не менее 4 гб, я в качестве примера выделю 8 гб)

Отлично, мы готовы к установке. Теперь осталось нажать на кнопку Install.

Но не спешите уходить т.к. это еще не все! Сейчас идет первый этап установки, а именно копирование образа, а если точнее, его обработка нашей программой. Мы пока никуда не уходим, и не выходим из приложения. Ждем пока закончится обработка. Вы это сразу поймете т.к. после копирования программа попросит вас подтвердить установку введя пароль от вашего устройства (или отпечаток, если имеется). Подтверждаем и начинается настоящая установка. Так же в шторке появляется уведомление где мы можем наблюдать процесс.

Рекомендую из приложения не выходить, если не хотите что либо сломать. Лучше просто дождитесь конца установка (Занимает от 3 до 15 минут, в зависимости от устройства)

После того как вы дождались конца установки, мы увидим соответствующее уведомление в шторке и в самом приложении. Дальше осталось только перезагрузиться в новую систему. Заходим в шторку, и нажимаем на кнопку Restart (перезагрузиться). И ждем запуска второй системы.

Вот и все, Перед нами новая система, полноценная, можно пользоваться.

А как вернуться обратно? Для этого достаточно заглянуть в шторку, там мы увидим аналогичное уведомление, и достаточно просто нажать на единственную кнопку «Перезагрузить» и мы вернемся в нашу основную систему.

Как удалить вторую систему и вернуть все как было?

Для этого вполне достаточно в основной системе в шторке нажать на кнопку «Discard» (Отменить/Удалить) и все. Вторая система удаляется и все остается как было.

Итоги

Ну-с, вот мы и закончили. Я в данной статье рассказал как установить, настроить и использовать кастомную прошивку в качестве дополнительной системы на 1 смартфоне. Для чего это можно использовать? Честно говоря, я не знаю. Как вариант, если вы разработчик приложений, то можете эту функцию использовать дабы проверить, как будет вести себя приложение в голом Android и с оболочкой (На примере MIUI). Что же касаемо обычных пользователей? Честно говоря, тут точного ответа я дать не могу, каждый сам найдет применение данной функции. А на этом пока что все)

При использовании материалов из данной статьи просьба указывать ссылку на оригинал!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *