Добавлен: 29.10.2018
Просмотров: 48038
Скачиваний: 190
916
Глава 10. Изучение конкретных примеров: Unix, Linux и Android
ложении, например, чтобы сделать все по-другому: пользователь, находясь в почтовом
приложении, может запросить добавление прикрепления, это вызовет для него запуск
активности в приложении камеры, чтобы можно было выбрать какой-нибудь снимок.
Диспетчер активностей
в процессе system_server
Процесс приложения камеры
Предоставленные URI
Задача: Pictures
ОТПРАВКА
content://pics/1
Сохраненное
состояние
ActivityRecord
(ComposeActivity)
ActivityRecord
(CameraActivity)
Для: ComposeActivity
URI: content://pics/1
Разре-
шено
Про
верка
PicturesProvider
Полномочия: «pics»
ComposeActivity
Процесс почтового приложения
Открыть
content://pics/1
Получить
данные
ВОЗОБНОВ-
ЛЕННАЯ
ОСТ
АНОВ-
ЛЕННАЯ
Рис. 10.43. Реализация возможности поделиться снимком с использованием
поставщика контента
Новое развитие ситуации показано на рис. 10.44. Оно почти идентично тому, что было
показано на рис. 10.43, единственным отличием является способ объединения актив-
ностей двух приложений, когда почтовое приложение запускает соответствующую
активность по выбору снимка в приложении камеры. После выбора снимка его URI
возвращается почтовому приложению, и в этот момент наше предоставление URI за-
писывается диспетчером активностей.
Этот подход очень эффективен, поскольку позволяет системе обеспечивать строгий
контроль над данными каждого отдельно взятого приложения, предоставляя конкрет-
ный доступ к данным по мере необходимости и не испытывая при этом надобности
в предупреждении пользователя о происходящем. Этим могут воспользоваться и мно-
гие другие пользовательские взаимодействия. Одним из вполне очевидных является
перетаскивание, но для определения видов взаимодействий, доступных приложениям,
Android получает и другую информацию, например из текущего фокуса окна.
Заключительный, широко используемый системой Android метод обеспечения без-
опасности представляет собой явные пользовательские интерфейсы для разрешения
и удаления конкретных типов доступа. В данном подходе существует некий способ,
позволяющий приложению показать, что оно может дополнительно предоставить
некоторую функциональную возможность, и предоставленный системой доверенный
пользовательский интерфейс, который обеспечит контроль над этим доступом.
10.8. Android
917
Типичным примером этого подхода является имеющаяся в Android архитектура метода
ввода данных. Метод ввода является конкретной службой, предоставляемой сторонним
приложением и позволяющей пользователю предоставлять приложению данные, как
правило, с помощью экранной клавиатуры. Это весьма конфиденциальный вид взаи-
модействия в системе, поскольку через приложение с методом ввода будет проходить
множество персональных данных, включая вводимые пользователем пароли.
Приложение показывает, что оно может быть методом ввода путем объявления в своем
манифесте службы с фильтром намерений, соответствующим действию для имеющего-
ся в системе протокола метода ввода. Но это не дает ему автоматического разрешения
становиться методом ввода, и пока не произойдет что-либо иное, песочница приложе-
ния не получит возможности выполнения таких операций.
Настройки системы Android включают пользовательский интерфейс для выбора ме-
тодов ввода. Этот интерфейс показывает все доступные методы ввода установленных
на данный момент приложений и то, включены они или нет. Если пользователь хочет
воспользоваться новым методом ввода после установки его приложения, он должен
зайти в интерфейс настройки системы и включить этот метод. При этом система так-
же может проинформировать пользователя, какие именно действия будет разрешено
совершать приложению.
Диспетчер активностей
в процессе system_server
Процесс приложения камеры
PicturesProvider
Полномочия: «pics»
ComposeActivity
Процесс почтового приложения
Предоставленные URI
Разре-
шено
Про-
верка
Открыть
content://pics/1
Получить
данные
Для: ComposeActivity
URI: content://pics/1
Задача: Pictures
ActivityRecord
(PicturePickerActivity)
ActivityRecord
(ComposeActivity)
Сохраненное
состояние
ПРИЕМ
content://pics/1
ПОЛУЧЕНИЕ
ВОЗОБНОВ-
ЛЕННАЯ
ОСТ
АНОВ-
ЛЕННАЯ
Рис. 10.44. Добавление возможности прикрепить снимок с использованием
поставщика контента
Даже если приложение включено в качестве метода ввода, для ограничения его влия-
ния в Android используются тонко выверенные технологии контроля доступа. Напри-
мер, фактически только приложение, использующееся в качестве текущего метода вво-
да, может иметь любую специальную итерацию. Если пользователь включил несколько
918
Глава 10. Изучение конкретных примеров: Unix, Linux и Android
методов ввода (например, программную клавиатуру и голосовой ввод), только один
активный в данный момент метод ввода будет иметь эти возможности доступными
в своей песочнице. Даже если текущий метод ввода ограничен в том, что он может
делать, существуют дополнительные политики, позволяющие ему взаимодействовать
только с тем окном, у которого в данный момент имеется фокус ввода.
10.8.12. Модель процесса
Традиционная модель процесса, имеющаяся в Linux, — это разветвление (с помощью
команды fork) для создания нового процесса, за которым следует команда exec для ини-
циализации этого процесса кодом, предназначенным для выполнения, с последующим
запуском его на выполнение. За управление этим выполнением отвечает оболочка,
разветвляя и выполняя процессы, необходимые для работы команд оболочки. Когда
происходит выход из этих команд, Linux удаляет процесс.
В Android процессы используются немного по-другому. Как говорилось в предыдущем
разделе, посвященном приложениям, частью Android, отвечающей за управление за-
пущенными приложениями, является диспетчер активностей. Он координирует запуск
новых прикладных процессов, определяет, что в них будет запускаться, и тот момент,
когда они уже будут не нужны.
Запуск процессов
Чтобы запустить новый процесс, диспетчер активностей должен быть связан с про-
цессом zygote. При первом запуске диспетчера активностей он создает выделенный
сокет с zygote, через который посылает команду, когда нуждается в запуске нового про-
цесса. Команда прежде всего дает описание создаваемой песочницы: UID, под которым
должен запуститься новый процесс, и любые другие ограничения, связанные с мерами
безопасности, которые будут применяться. Таким образом, zygote должен запускаться
с root-правами: при разветвлении он выполняет соответствующую настройку для UID,
с которым процесс будет запущен, и в конце сбрасывает root-права и изменяет процесс,
присваивая ему нужный UID.
Вспомним, что в предыдущем рассмотрении Android-приложений говорилось, что
диспетчер активностей обслуживает динамическую информацию о выполнении ак-
тивностей (см. рис. 10.32), служб (см. рис. 10.37), рассылок (для получателей, как на
рис. 10.39) и поставщиков контента (см. рис. 10.40). Он использует эту информацию
для контроля над созданием прикладных процессов и управления ими. Например,
как показано на рис. 10.32, когда программа запуска приложения осуществляет вызов
системы с новым намерением на запуск активности, за то, чтобы это новое приложение
работало, отвечает диспетчер активностей.
Порядок запуска активности в новом процессе показан на рис. 10.45. А вот как выгля-
дят подробности каждого этапа:
1. Какой-нибудь существующий процесс (например, предназначенный для запуска
приложений) осуществляет вызов диспетчера активностей с намерением, дающим
описание новой активности, которую он собирается запустить.
2. Диспетчер активностей просит, чтобы диспетчер пакетов провел разрешение на-
мерения до явного компонента.
10.8. Android
919
3. Диспетчер активностей определяет, что прикладной процесс еще не запущен, а за-
тем просит zygote создать новый процесс с соответствующим UID.
4. Zygote выполняет ветвление, создает новый процесс, являющийся клоном себя
самого, сбрасывает права и устанавливает его UID песочнице приложения, а за-
тем завершает инициализацию Dalvik в этом процессе для полноценной работы
среды выполнения Java. Например, после ветвления должны запускаться такие
потоки, как сборщик мусора.
5. Новый процесс, представляющий собой клон zygote с полностью установленной
и работающей Java-средой, осуществляет обратный вызов диспетчера активностей
с вопросом: «Для чего я нужен?».
6. Диспетчер активностей возвращает ему полную информацию о запускаемом в нем
приложении, например о том, где найти его код.
7. Новый процесс загружает код запускаемого приложения.
8. Диспетчер активностей отправляет новому процессу любую ожидающую опера-
цию, в данном случае «Запустить активность X».
9. Новый процесс получает команду на запуск активности, создает экземпляр соот-
ветствующего Java-класса и выполняет его.
Процесс system_server
Прикладной процесс
Экземпляр активности
Код приложения
Android-среда
PackageManagerService
startActivity()
ActivityManagerService
«Кто я такой?»
Загрузка кода
этого приложения
Создать экземпляр
этого класса
Процесс zygote
Создать новый
процесс
Разрешить
намерение
2
1
3
5
6
8
9
7
4
Рис. 10.45. Этапы запуска нового прикладного процесса
Обратите внимание на то, что при запуске активности процесс приложения мог быть
уже запущен. В таком случае диспетчер активностей просто пропустит все до конца, от-
правляя процессу новую команду, предписывающую ему создать и запустить экземпляр
920
Глава 10. Изучение конкретных примеров: Unix, Linux и Android
соответствующего компонента. Это может привести к появлению при необходимости
нового экземпляра активности, запущенного в приложении, как было показано на
рис. 10.36.
Жизненный цикл процессов
Диспетчер активностей отвечает также за определение того момента, когда процессы
больше не нужны. Он отслеживает все активности, получатели, службы и поставщики
контента, запущенные в процессе, в результате чего может определить, насколько важен
(или неважен) тот или иной процесс.
Вспомним, что имеющийся в Android механизм устранения дефицита памяти, нахо-
дящийся в ядре, использует показатель oom_adj процесса для выстраивания четкого
порядка, позволяющего определить, какие процессы он должен уничтожить. Диспетчер
активностей отвечает за настройку показателей oom_adj всех процессов, которые со-
ответствующим образом основаны на состоянии этих процессов, классифицируя их
в основных категориях использования. Эти основные категории показаны в табл. 10.17,
где сначала идут наиболее важные. В последнем столбце показано типовое значение
oom_adj, которое назначается процессу данного типа.
Таблица 10.17. Категории важности процесса
Категория
Описание
oom_adj
SYSTEM
Системные процессы и демоны
−16
PERSISTENT
Постоянно работающие прикладные процессы
−12
FOREGROUND
Процессы, взаимодействующие в данный момент с пользо-
вателем
0
VISIBLE
Процессы, видимые пользователю
1
PERCEPTIBLE
Что-то, о чем знает пользователь
2
SERVICE
Запущенные фоновые службы
3
HOME
Главный (запускающий) процесс
4
CACHED
Неиспользуемый процесс
5
Теперь, когда уровень свободной оперативной памяти снизится, система настроит
процессы таким образом, чтобы механизм устранения дефицита памяти сначала унич-
тожил кэшированные процессы, стараясь восстановить достаточный объем нужной
оперативной памяти, затем главный процесс, процессы служб и далее вверх по списку.
Внутри конкретного уровня oom_adj он сначала уничтожит процессы, которые ис-
пользуют больше оперативной памяти, а затем перейдет к уничтожению тех, которые
используют меньше памяти.
Мы уже видели, как в системе Android принимаются решения, когда запускать про-
цессы и как в ней эти процессы распределяются по категориям в зависимости от
важности. Теперь нужно решить, когда следует выходит из процессов, не так ли? Или
же нужно ли вообще что-либо делать в этом плане? Ответом будет: ничего делать не
нужно. В Android прикладные процессы никогда не имеют явно обозначенного вы-
хода. Система просто оставляет ненужные процессы в покое, полагаясь на то, что при
необходимости ядро воспользуется ими.